From f223be15cda9d281713d9e4f59183f1bbe13a910 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 19 Jan 2016 12:51:56 -0800 Subject: [PATCH] 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}",