fix unknowns added to maps by schemaMap

The legacy diff process inserts unknown values into an optional+computed
map. Fix these up in post-plan normalization process, by looking for
known strings that were changed to unknown.
This commit is contained in:
James Bardin 2019-03-29 11:24:14 -04:00
parent 009df443f7
commit 86e30add98
2 changed files with 43 additions and 6 deletions

View File

@ -1184,11 +1184,8 @@ func normalizeNullValues(dst, src cty.Value, preferDst bool) cty.Value {
dstMap = map[string]cty.Value{}
}
ei := src.ElementIterator()
for ei.Next() {
k, v := ei.Element()
key := k.AsString()
srcMap := src.AsValueMap()
for key, v := range srcMap {
dstVal := dstMap[key]
if dstVal == cty.NilVal {
if preferDst && ty.IsMapType() {
@ -1211,6 +1208,24 @@ func normalizeNullValues(dst, src cty.Value, preferDst bool) cty.Value {
}
if ty.IsMapType() {
// helper/schema will populate an optional+computed map with
// unknowns which we have to fixup here.
// It would be preferable to simply prevent any known value from
// becoming unknown, but concessions have to be made to retain the
// broken legacy behavior when possible.
for k, srcVal := range srcMap {
if !srcVal.IsNull() && srcVal.IsKnown() {
dstVal, ok := dstMap[k]
if !ok {
continue
}
if !dstVal.IsNull() && !dstVal.IsKnown() {
dstMap[k] = srcVal
}
}
}
return cty.MapVal(dstMap)
}

View File

@ -909,7 +909,7 @@ func TestNormalizeNullValues(t *testing.T) {
}),
}),
},
// the empty list should be transferred, but the new unknown show not be overridden
// the empty list should be transferred, but the new unknown should not be overridden
{
Src: cty.ObjectVal(map[string]cty.Value{
"network_interface": cty.ListVal([]cty.Value{
@ -942,6 +942,28 @@ func TestNormalizeNullValues(t *testing.T) {
}),
Plan: true,
},
{
// fix unknowns added to a map
Src: cty.ObjectVal(map[string]cty.Value{
"map": cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("a"),
"b": cty.StringVal(""),
}),
}),
Dst: cty.ObjectVal(map[string]cty.Value{
"map": cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("a"),
"b": cty.UnknownVal(cty.String),
}),
}),
Expect: cty.ObjectVal(map[string]cty.Value{
"map": cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("a"),
"b": cty.StringVal(""),
}),
}),
Plan: true,
},
} {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
got := normalizeNullValues(tc.Dst, tc.Src, tc.Plan)