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.
This commit is contained in:
Martin Atkins 2017-04-07 15:30:53 -07:00
parent 46994483e1
commit e4a5d36127
1 changed files with 20 additions and 15 deletions

View File

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