core: EvalVariableBlock to decode maps and slices more carefully

Previously this function was depending on the mapstructure behavior of
failing with an error when trying to decode a map into a list or
vice-versa, but mapstructure's WeakDecode behavior changed so that it
will go to greater lengths to coerce the given value to fit into the
target type, causing us to mis-handle certain ambigous cases.

Here we exert a bit more control over what's going on by using 'reflect'
to first check whether we have a slice or map value and only then try
to decode into one with mapstructure. This allows us to still rely on
mapstructure's ability to decode nested structures but ensure that lists
and maps never get implicitly converted to each other.
pull/13478/head
Martin Atkins 9 years ago
parent 46994483e1
commit e4a5d36127

@ -123,22 +123,27 @@ func (n *EvalVariableBlock) Eval(ctx EvalContext) (interface{}, error) {
// Get our configuration
rc := *n.Config
for k, v := range rc.Config {
var vString string
if err := hilmapstructure.WeakDecode(v, &vString); err == nil {
n.VariableValues[k] = vString
continue
}
vKind := reflect.ValueOf(v).Type().Kind()
var vMap map[string]interface{}
if err := hilmapstructure.WeakDecode(v, &vMap); err == nil {
n.VariableValues[k] = vMap
continue
}
var vSlice []interface{}
if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil {
n.VariableValues[k] = vSlice
continue
switch vKind {
case reflect.Slice:
var vSlice []interface{}
if err := hilmapstructure.WeakDecode(v, &vSlice); err == nil {
n.VariableValues[k] = vSlice
continue
}
case reflect.Map:
var vMap map[string]interface{}
if err := hilmapstructure.WeakDecode(v, &vMap); err == nil {
n.VariableValues[k] = vMap
continue
}
default:
var vString string
if err := hilmapstructure.WeakDecode(v, &vString); err == nil {
n.VariableValues[k] = vString
continue
}
}
return nil, fmt.Errorf("Variable value for %s is not a string, list or map type", k)

Loading…
Cancel
Save