From 54de9057ba2b6cfecab462dcff6e83ebe383118d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 19 Jan 2016 12:37:55 -0800 Subject: [PATCH 1/3] terraform: failing test case --- terraform/context_plan_test.go | 23 +++++++++++++++++++ terraform/terraform_test.go | 12 ++++++++++ .../test-fixtures/plan-escaped-var/main.tf | 3 +++ 3 files changed, 38 insertions(+) create mode 100644 terraform/test-fixtures/plan-escaped-var/main.tf diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index e91fc7747..7963bdb7f 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -104,6 +104,29 @@ func TestContext2Plan_emptyDiff(t *testing.T) { } } +func TestContext2Plan_escapedVar(t *testing.T) { + m := testModule(t, "plan-escaped-var") + p := testProvider("aws") + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + }) + + plan, err := ctx.Plan() + if err != nil { + t.Fatalf("err: %s", err) + } + + actual := strings.TrimSpace(plan.String()) + expected := strings.TrimSpace(testTerraformPlanEscapedVarStr) + if actual != expected { + t.Fatalf("bad:\n%s", actual) + } +} + func TestContext2Plan_minimal(t *testing.T) { m := testModule(t, "plan-empty") p := testProvider("aws") diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 3b1653f43..0fc0b71fe 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -983,6 +983,18 @@ STATE: ` +const testTerraformPlanEscapedVarStr = ` +DIFF: + +CREATE: aws_instance.foo + foo: "" => "bar-${baz}" + type: "" => "aws_instance" + +STATE: + + +` + const testTerraformPlanModulesStr = ` DIFF: diff --git a/terraform/test-fixtures/plan-escaped-var/main.tf b/terraform/test-fixtures/plan-escaped-var/main.tf new file mode 100644 index 000000000..5a017207c --- /dev/null +++ b/terraform/test-fixtures/plan-escaped-var/main.tf @@ -0,0 +1,3 @@ +resource "aws_instance" "foo" { + foo = "bar-$${baz}" +} From f223be15cda9d281713d9e4f59183f1bbe13a910 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 19 Jan 2016 12:51:56 -0800 Subject: [PATCH 2/3] config: eval HEL as long as the result changes [GH-2909] --- config/interpolate_walk.go | 12 +++++++++--- config/lang/eval_test.go | 8 ++++++++ config/raw_config_test.go | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/config/interpolate_walk.go b/config/interpolate_walk.go index adcb5e32c..075355831 100644 --- a/config/interpolate_walk.go +++ b/config/interpolate_walk.go @@ -118,9 +118,15 @@ func (w *interpolationWalker) Primitive(v reflect.Value) error { return err } - // If the AST we got is just a literal string value, then we ignore it - if _, ok := astRoot.(*ast.LiteralNode); ok { - return nil + // If the AST we got is just a literal string value with the same + // value then we ignore it. We have to check if its the same value + // because it is possible to input a string, get out a string, and + // have it be different. For example: "foo-$${bar}" turns into + // "foo-${bar}" + if n, ok := astRoot.(*ast.LiteralNode); ok { + if s, ok := n.Value.(string); ok && s == v.String() { + return nil + } } if w.ContextF != nil { diff --git a/config/lang/eval_test.go b/config/lang/eval_test.go index 63c7ce984..001963014 100644 --- a/config/lang/eval_test.go +++ b/config/lang/eval_test.go @@ -24,6 +24,14 @@ func TestEval(t *testing.T) { ast.TypeString, }, + { + "foo $${bar}", + nil, + false, + "foo ${bar}", + ast.TypeString, + }, + { "foo ${bar}", &ast.BasicScope{ diff --git a/config/raw_config_test.go b/config/raw_config_test.go index 1b5de3e16..81d3f20c1 100644 --- a/config/raw_config_test.go +++ b/config/raw_config_test.go @@ -114,6 +114,38 @@ func TestRawConfig_double(t *testing.T) { } } +func TestRawConfigInterpolate_escaped(t *testing.T) { + raw := map[string]interface{}{ + "foo": "bar-$${baz}", + } + + rc, err := NewRawConfig(raw) + if err != nil { + t.Fatalf("err: %s", err) + } + + // Before interpolate, Config() should be the raw + if !reflect.DeepEqual(rc.Config(), raw) { + t.Fatalf("bad: %#v", rc.Config()) + } + + if err := rc.Interpolate(nil); err != nil { + t.Fatalf("err: %s", err) + } + + actual := rc.Config() + expected := map[string]interface{}{ + "foo": "bar-${baz}", + } + + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad: %#v", actual) + } + if len(rc.UnknownKeys()) != 0 { + t.Fatalf("bad: %#v", rc.UnknownKeys()) + } +} + func TestRawConfig_merge(t *testing.T) { raw1 := map[string]interface{}{ "foo": "${var.foo}", From 693736b52ad1c60d84b604ca12661133e8fbbc59 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 19 Jan 2016 13:17:47 -0800 Subject: [PATCH 3/3] config: fix tests --- config/interpolate_walk_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/config/interpolate_walk_test.go b/config/interpolate_walk_test.go index fc7c8b549..b5c9a3a92 100644 --- a/config/interpolate_walk_test.go +++ b/config/interpolate_walk_test.go @@ -18,7 +18,9 @@ func TestInterpolationWalker_detect(t *testing.T) { Input: map[string]interface{}{ "foo": "$${var.foo}", }, - Result: nil, + Result: []string{ + "Literal(TypeString, ${var.foo})", + }, }, { @@ -114,7 +116,7 @@ func TestInterpolationWalker_replace(t *testing.T) { "foo": "$${var.foo}", }, Output: map[string]interface{}{ - "foo": "$${var.foo}", + "foo": "bar", }, Value: "bar", },