core: Fix slice element keys on interpolateWalk

Part of the interpolation walk is to detect keys which involve computed
values and therefore cannot be resolved at this time. The interplation
walker keeps sufficient state to be able to populate the ResourceConfig
with a slice of such keys.

Previously they didn't take slice indexes into account, so in the
following case:

```
"services": []interface{}{
    map[string]interface{}{
        "elb": "___something computed___",
    },
    map[string]interface{}{
        "elb": "___something else computed___",
    },
    map[string]interface{}{
        "elb": "not computed",
    },
}
```

Unknown keys would be populated as follows:

```
services.elb
services.elb
```

This is not sufficient information to be useful, as it is impossible to
distinguish which of the `services.elb`s are unknown vs not.

This commit therefore retains the slice indexes as part of the key for
unknown keys - producing for the example above:

```
services.0.elb
services.1.elb
```
This commit is contained in:
James Nugent 2016-07-07 19:15:32 +01:00
parent 088feb933f
commit c6e03cba96

View File

@ -54,6 +54,9 @@ type interpolationWalkerContextFunc func(reflectwalk.Location, ast.Node)
func (w *interpolationWalker) Enter(loc reflectwalk.Location) error {
w.loc = loc
if loc == reflectwalk.WalkLoc {
w.sliceIndex = -1
}
return nil
}
@ -72,6 +75,7 @@ func (w *interpolationWalker) Exit(loc reflectwalk.Location) error {
w.cs = w.cs[:len(w.cs)-1]
case reflectwalk.SliceElem:
w.csKey = w.csKey[:len(w.csKey)-1]
w.sliceIndex = -1
}
return nil
@ -85,7 +89,13 @@ func (w *interpolationWalker) Map(m reflect.Value) error {
func (w *interpolationWalker) MapElem(m, k, v reflect.Value) error {
w.csData = k
w.csKey = append(w.csKey, k)
w.key = append(w.key, k.String())
if w.sliceIndex != -1 {
w.key = append(w.key, fmt.Sprintf("%d.%s", w.sliceIndex, k.String()))
} else {
w.key = append(w.key, k.String())
}
w.lastValue = v
return nil
}
@ -164,6 +174,7 @@ func (w *interpolationWalker) Primitive(v reflect.Value) error {
} else if replaceVal == UnknownVariableValue {
remove = true
}
if remove {
w.removeCurrent()
return nil