diff --git a/config/lang/transform_fixed.go b/config/lang/transform_fixed.go new file mode 100644 index 0000000000..c551423df3 --- /dev/null +++ b/config/lang/transform_fixed.go @@ -0,0 +1,26 @@ +package lang + +import ( + "github.com/hashicorp/terraform/config/lang/ast" +) + +// FixedValueTransform transforms an AST to return a fixed value for +// all interpolations. i.e. you can make "hello ${anything}" always +// turn into "hello foo". +func FixedValueTransform(root ast.Node, Value *ast.LiteralNode) ast.Node { + // We visit the nodes in top-down order + result := root + switch n := result.(type) { + case *ast.Concat: + for i, v := range n.Exprs { + n.Exprs[i] = FixedValueTransform(v, Value) + } + case *ast.LiteralNode: + // We keep it as-is + default: + // Anything else we replace + result = Value + } + + return result +} diff --git a/config/lang/transform_fixed_test.go b/config/lang/transform_fixed_test.go new file mode 100644 index 0000000000..c5e5a1ca3a --- /dev/null +++ b/config/lang/transform_fixed_test.go @@ -0,0 +1,48 @@ +package lang + +import ( + "reflect" + "testing" + + "github.com/hashicorp/terraform/config/lang/ast" +) + +func TestFixedValueTransform(t *testing.T) { + cases := []struct { + Input ast.Node + Output ast.Node + }{ + { + &ast.LiteralNode{Value: 42}, + &ast.LiteralNode{Value: 42}, + }, + + { + &ast.VariableAccess{Name: "bar"}, + &ast.LiteralNode{Value: "foo"}, + }, + + { + &ast.Concat{ + Exprs: []ast.Node{ + &ast.VariableAccess{Name: "bar"}, + &ast.LiteralNode{Value: 42}, + }, + }, + &ast.Concat{ + Exprs: []ast.Node{ + &ast.LiteralNode{Value: "foo"}, + &ast.LiteralNode{Value: 42}, + }, + }, + }, + } + + value := &ast.LiteralNode{Value: "foo"} + for _, tc := range cases { + actual := FixedValueTransform(tc.Input, value) + if !reflect.DeepEqual(actual, tc.Output) { + t.Fatalf("bad: %#v\n\nInput: %#v", actual, tc.Input) + } + } +}