terraform/config/variable.go

79 lines
1.6 KiB
Go

package config
import (
"fmt"
"reflect"
"regexp"
"strings"
)
// varRegexp is a regexp that matches variables such as ${foo.bar}
var varRegexp *regexp.Regexp
func init() {
varRegexp = regexp.MustCompile(`(?i)(\$+)\{([-.a-z0-9_]+)\}`)
}
// variableDetectWalker implements interfaces for the reflectwalk package
// (github.com/mitchellh/reflectwalk) that can be used to automatically
// pull out the variables that need replacing.
type variableDetectWalker struct {
Variables map[string]InterpolatedVariable
}
func (w *variableDetectWalker) Primitive(v reflect.Value) error {
// We only care about strings
if v.Kind() != reflect.String {
return nil
}
// XXX: This can be a lot more efficient if we used a real
// parser. A regexp is a hammer though that will get this working.
matches := varRegexp.FindAllStringSubmatch(v.String(), -1)
if len(matches) == 0 {
return nil
}
for _, match := range matches {
dollars := len(match[1])
// If there are even amounts of dollar signs, then it is escaped
if dollars%2 == 0 {
continue
}
// Otherwise, record it
key := match[2]
if w.Variables == nil {
w.Variables = make(map[string]InterpolatedVariable)
}
if _, ok := w.Variables[key]; ok {
continue
}
var err error
var iv InterpolatedVariable
if strings.Index(key, ".") == -1 {
return fmt.Errorf(
"Interpolated variable '%s' has bad format. "+
"Did you mean 'var.%s'?",
key, key)
}
if strings.HasPrefix(key, "var.") {
iv, err = NewUserVariable(key)
} else {
iv, err = NewResourceVariable(key)
}
if err != nil {
return err
}
w.Variables[key] = iv
}
return nil
}