From b979d8927e3cf2a91c6f9fb0840531a4f7341553 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 26 Oct 2016 23:24:23 -0400 Subject: [PATCH] config: use ast.TypeUnknown and don't remove computed values --- config/interpolate.go | 4 ++++ config/interpolate_test.go | 16 ++++++++++++++++ config/interpolate_walk.go | 7 +++++-- config/interpolate_walk_test.go | 10 ++++++++-- config/raw_config.go | 21 --------------------- config/raw_config_test.go | 11 ++++++----- 6 files changed, 39 insertions(+), 30 deletions(-) diff --git a/config/interpolate.go b/config/interpolate.go index bb526bf6a..5867c6333 100644 --- a/config/interpolate.go +++ b/config/interpolate.go @@ -149,6 +149,10 @@ func (v *ModuleVariable) FullKey() string { return v.key } +func (v *ModuleVariable) GoString() string { + return fmt.Sprintf("*%#v", *v) +} + func NewPathVariable(key string) (*PathVariable, error) { var fieldType PathValueType parts := strings.SplitN(key, ".", 2) diff --git a/config/interpolate_test.go b/config/interpolate_test.go index ac28ad0fb..e5224ee0d 100644 --- a/config/interpolate_test.go +++ b/config/interpolate_test.go @@ -240,6 +240,22 @@ func TestDetectVariables(t *testing.T) { }, }, }, + + { + `foo ${module.foo.output["key"]}`, + []InterpolatedVariable{ + &ModuleVariable{ + Name: "foo", + Field: "output", + key: "module.foo.output", + }, + &ModuleVariable{ + Name: "foo", + Field: "output", + key: "module.foo.output", + }, + }, + }, } for _, tc := range cases { diff --git a/config/interpolate_walk.go b/config/interpolate_walk.go index 720a8b285..fd826012d 100644 --- a/config/interpolate_walk.go +++ b/config/interpolate_walk.go @@ -176,8 +176,11 @@ func (w *interpolationWalker) Primitive(v reflect.Value) error { } if remove { - w.removeCurrent() - return nil + // Append the key to the unknown keys + w.unknownKeys = append(w.unknownKeys, strings.Join(w.key, ".")) + + //w.removeCurrent() + //return nil } resultVal := reflect.ValueOf(replaceVal) diff --git a/config/interpolate_walk_test.go b/config/interpolate_walk_test.go index 35b8f1f57..e3794b12a 100644 --- a/config/interpolate_walk_test.go +++ b/config/interpolate_walk_test.go @@ -169,8 +169,14 @@ func TestInterpolationWalker_replace(t *testing.T) { "bing", }, }, - Output: map[string]interface{}{}, - Value: []interface{}{UnknownVariableValue, "baz"}, + Output: map[string]interface{}{ + "foo": []interface{}{ + UnknownVariableValue, + "baz", + "bing", + }, + }, + Value: []interface{}{UnknownVariableValue, "baz"}, }, } diff --git a/config/raw_config.go b/config/raw_config.go index 73d6a5e2b..3bcc62412 100644 --- a/config/raw_config.go +++ b/config/raw_config.go @@ -127,27 +127,6 @@ func (r *RawConfig) Interpolate(vs map[string]ast.Variable) error { config := langEvalConfig(vs) return r.interpolate(func(root ast.Node) (interface{}, error) { - // We detect the variables again and check if the value of any - // of the variables is the computed value. If it is, then we - // treat this entire value as computed. - // - // We have to do this here before the `lang.Eval` because - // if any of the variables it depends on are computed, then - // the interpolation can fail at runtime for other reasons. Example: - // `${count.index+1}`: in a world where `count.index` is computed, - // this would fail a type check since the computed placeholder is - // a string, but realistically the whole value is just computed. - vars, err := DetectVariables(root) - if err != nil { - return "", err - } - for _, v := range vars { - varVal, ok := vs[v.FullKey()] - if ok && varVal.Value == UnknownVariableValue { - return UnknownVariableValue, nil - } - } - // None of the variables we need are computed, meaning we should // be able to properly evaluate. result, err := hil.Eval(root, config) diff --git a/config/raw_config_test.go b/config/raw_config_test.go index 5d4b881a4..2df9aef62 100644 --- a/config/raw_config_test.go +++ b/config/raw_config_test.go @@ -191,7 +191,7 @@ func TestRawConfig_merge(t *testing.T) { }, "var.baz": ast.Variable{ Value: UnknownVariableValue, - Type: ast.TypeString, + Type: ast.TypeUnknown, }, } if err := rc2.Interpolate(vars); err != nil { @@ -216,6 +216,7 @@ func TestRawConfig_merge(t *testing.T) { expected := map[string]interface{}{ "foo": "foovalue", "bar": "barvalue", + "baz": UnknownVariableValue, } if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: %#v", actual) @@ -250,7 +251,7 @@ func TestRawConfig_unknown(t *testing.T) { vars := map[string]ast.Variable{ "var.bar": ast.Variable{ Value: UnknownVariableValue, - Type: ast.TypeString, + Type: ast.TypeUnknown, }, } if err := rc.Interpolate(vars); err != nil { @@ -258,7 +259,7 @@ func TestRawConfig_unknown(t *testing.T) { } actual := rc.Config() - expected := map[string]interface{}{} + expected := map[string]interface{}{"foo": UnknownVariableValue} if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: %#v", actual) @@ -283,7 +284,7 @@ func TestRawConfig_unknownPartial(t *testing.T) { vars := map[string]ast.Variable{ "var.bar": ast.Variable{ Value: UnknownVariableValue, - Type: ast.TypeString, + Type: ast.TypeUnknown, }, } if err := rc.Interpolate(vars); err != nil { @@ -291,7 +292,7 @@ func TestRawConfig_unknownPartial(t *testing.T) { } actual := rc.Config() - expected := map[string]interface{}{} + expected := map[string]interface{}{"foo": UnknownVariableValue} if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: %#v", actual)