config: keep track of unknown keys during interpolate

This commit is contained in:
Mitchell Hashimoto 2014-06-12 17:00:50 -07:00
parent 1af5aee146
commit 0ad9d9ddc7
3 changed files with 71 additions and 3 deletions

View File

@ -1,3 +1 @@
package config

View File

@ -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, "."))
}

View File

@ -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)
}
}
}