diff --git a/config/raw_config_test.go b/config/raw_config_test.go index b663f62c47..d912156bec 100644 --- a/config/raw_config_test.go +++ b/config/raw_config_test.go @@ -1,3 +1 @@ package config - - diff --git a/config/variable.go b/config/variable.go index 4fac2c1223..ce83097cac 100644 --- a/config/variable.go +++ b/config/variable.go @@ -99,8 +99,10 @@ func (w *variableDetectWalker) Primitive(v reflect.Value) error { // will _panic_. The variableDetectWalker will tell you all variables // you need. type variableReplaceWalker struct { - Values map[string]string + Values map[string]string + UnknownKeys []string + key []string loc reflectwalk.Location m, mk reflect.Value cs []reflect.Value @@ -118,6 +120,8 @@ func (w *variableReplaceWalker) Exit(loc reflectwalk.Location) error { switch loc { case reflectwalk.Map: w.cs = w.cs[:len(w.cs)-1] + case reflectwalk.MapValue: + w.key = w.key[:len(w.key)-1] } return nil @@ -132,6 +136,7 @@ func (w *variableReplaceWalker) MapElem(m, k, v reflect.Value) error { w.m = m w.mk = k w.csData = k + w.key = append(w.key, k.String()) return nil } @@ -202,4 +207,7 @@ func (w *variableReplaceWalker) removeCurrent() { k := w.csData.(reflect.Value) c.SetMapIndex(k, val) } + + // Append the key to the unknown keys + w.UnknownKeys = append(w.UnknownKeys, strings.Join(w.key, ".")) } diff --git a/config/variable_test.go b/config/variable_test.go index 1579a8b99b..bd3a6a96e6 100644 --- a/config/variable_test.go +++ b/config/variable_test.go @@ -183,3 +183,65 @@ func TestVariableReplaceWalker(t *testing.T) { } } } + +func TestVariableReplaceWalker_unknown(t *testing.T) { + cases := []struct { + Input interface{} + Output interface{} + Keys []string + }{ + { + map[string]interface{}{ + "foo": "bar", + "bar": "hello${var.unknown}world", + }, + map[string]interface{}{ + "foo": "bar", + }, + []string{"bar"}, + }, + { + map[string]interface{}{ + "foo": []string{"foo", "${var.unknown}", "bar"}, + }, + map[string]interface{}{}, + []string{"foo"}, + }, + { + map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "${var.unknown}", + }, + }, + map[string]interface{}{ + "foo": map[string]interface{}{}, + }, + []string{"foo.bar"}, + }, + } + + for i, tc := range cases { + var input interface{} = tc.Input + w := &variableReplaceWalker{ + Values: map[string]string{ + "var.unknown": UnknownVariableValue, + }, + } + + if reflect.ValueOf(tc.Input).Kind() == reflect.String { + input = &tc.Input + } + + if err := reflectwalk.Walk(input, w); err != nil { + t.Fatalf("err: %s", err) + } + + if !reflect.DeepEqual(tc.Input, tc.Output) { + t.Fatalf("bad %d: %#v", i, tc.Input) + } + + if !reflect.DeepEqual(tc.Keys, w.UnknownKeys) { + t.Fatalf("bad: %#v", w.UnknownKeys) + } + } +}