config: parsing of local.foo variables for interpolation

This commit is contained in:
Martin Atkins 2017-07-01 09:23:42 -07:00
parent f6797d6cb0
commit d41d58967f
2 changed files with 56 additions and 12 deletions

View File

@ -101,6 +101,12 @@ type UserVariable struct {
key string
}
// A LocalVariable is a variable that references a local value defined within
// the current module, via a "locals" block. This looks like "${local.foo}".
type LocalVariable struct {
Name string
}
func NewInterpolatedVariable(v string) (InterpolatedVariable, error) {
if strings.HasPrefix(v, "count.") {
return NewCountVariable(v)
@ -112,6 +118,8 @@ func NewInterpolatedVariable(v string) (InterpolatedVariable, error) {
return NewTerraformVariable(v)
} else if strings.HasPrefix(v, "var.") {
return NewUserVariable(v)
} else if strings.HasPrefix(v, "local.") {
return NewLocalVariable(v)
} else if strings.HasPrefix(v, "module.") {
return NewModuleVariable(v)
} else if !strings.ContainsRune(v, '.') {
@ -331,6 +339,25 @@ func (v *UserVariable) GoString() string {
return fmt.Sprintf("*%#v", *v)
}
func NewLocalVariable(key string) (*LocalVariable, error) {
name := key[len("local."):]
if idx := strings.Index(name, "."); idx > -1 {
return nil, fmt.Errorf("Can't use dot (.) attribute access in local.%s; use square bracket indexing", name)
}
return &LocalVariable{
Name: name,
}, nil
}
func (v *LocalVariable) FullKey() string {
return fmt.Sprintf("local.%s", v.Name)
}
func (v *LocalVariable) GoString() string {
return fmt.Sprintf("*%#v", *v)
}
// DetectVariables takes an AST root and returns all the interpolated
// variables that are detected in the AST tree.
func DetectVariables(root ast.Node) ([]InterpolatedVariable, error) {

View File

@ -9,10 +9,10 @@ import (
)
func TestNewInterpolatedVariable(t *testing.T) {
cases := []struct {
Input string
Result InterpolatedVariable
Error bool
tests := []struct {
Input string
Want InterpolatedVariable
Error bool
}{
{
"var.foo",
@ -22,6 +22,18 @@ func TestNewInterpolatedVariable(t *testing.T) {
},
false,
},
{
"local.foo",
&LocalVariable{
Name: "foo",
},
false,
},
{
"local.foo.nope",
nil,
true,
},
{
"module.foo.bar",
&ModuleVariable{
@ -73,14 +85,19 @@ func TestNewInterpolatedVariable(t *testing.T) {
},
}
for i, tc := range cases {
actual, err := NewInterpolatedVariable(tc.Input)
if err != nil != tc.Error {
t.Fatalf("%d. Error: %s", i, err)
}
if !reflect.DeepEqual(actual, tc.Result) {
t.Fatalf("%d bad: %#v", i, actual)
}
for i, test := range tests {
t.Run(test.Input, func(t *testing.T) {
got, err := NewInterpolatedVariable(test.Input)
if err != nil != test.Error {
t.Errorf("%d. Error: %s", i, err)
}
if !test.Error && !reflect.DeepEqual(got, test.Want) {
t.Errorf(
"wrong result\ninput: %s\ngot: %#v\nwant: %#v",
test.Input, got, test.Want,
)
}
})
}
}