helper/plugin: fix panic with empty objects in normalizeNullValues

cty.Value.AsValueMap can return nil if called on an empty map or object.
The logic above was dealing with that case for maps, but object types
were falling through into this codepath and panicking when trying to
assign a new key into the nil dstMap.

This also includes a bonus fix where we were calling ty.ElementType in
a switch case that accepts object types. Object types don't have a single
element type, so we can't call ElementType on those (that also panics)
but we _can_ use the type of the value we selected from src to construct
our placeholder null value.
This commit is contained in:
Martin Atkins 2019-02-13 15:15:15 -08:00
parent 8f3ee1800d
commit fedbd6c3b8
2 changed files with 15 additions and 4 deletions

View File

@ -1209,11 +1209,12 @@ func normalizeNullValues(dst, src cty.Value, plan bool) cty.Value {
switch {
case ty.IsMapType(), ty.IsObjectType():
var dstMap map[string]cty.Value
if dst.IsNull() {
dstMap = map[string]cty.Value{}
} else {
if !dst.IsNull() {
dstMap = dst.AsValueMap()
}
if dstMap == nil {
dstMap = map[string]cty.Value{}
}
ei := src.ElementIterator()
for ei.Next() {
@ -1226,7 +1227,7 @@ func normalizeNullValues(dst, src cty.Value, plan bool) cty.Value {
// let plan shape this map however it wants
continue
}
dstVal = cty.NullVal(ty.ElementType())
dstVal = cty.NullVal(v.Type())
}
dstMap[key] = normalizeNullValues(dstVal, v, plan)
}

View File

@ -877,6 +877,16 @@ func TestNormalizeNullValues(t *testing.T) {
}),
Plan: true,
},
{
Src: cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("a"),
}),
Dst: cty.EmptyObjectVal,
Expect: cty.ObjectVal(map[string]cty.Value{
"a": cty.NullVal(cty.String),
}),
Plan: true,
},
// a list in an object in a list, going from null to empty
{