Merge pull request #21291 from hashicorp/jbardin/read-empty-containers

only hold back empty container changes in apply
This commit is contained in:
James Bardin 2019-05-13 19:20:07 -04:00 committed by GitHub
commit ea6b5b010a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 12 deletions

View File

@ -1163,25 +1163,22 @@ func normalizeNullValues(dst, src cty.Value, apply bool) cty.Value {
if !src.IsNull() && !src.IsKnown() {
// Return src during plan to retain unknown interpolated placeholders,
// which could be lost if we're only updating a resource. If this is a
// read scenario, then there shouldn't be any unknowns all.
// read scenario, then there shouldn't be any unknowns at all.
if dst.IsNull() && !apply {
return src
}
return dst
}
// handle null/empty changes for collections
if ty.IsCollectionType() {
if src.IsNull() && !dst.IsNull() && dst.IsKnown() {
if dst.LengthInt() == 0 {
return src
}
}
// Handle null/empty changes for collections during apply.
// A change between null and empty values prefers src to make sure the state
// is consistent between plan and apply.
if ty.IsCollectionType() && apply {
dstEmpty := !dst.IsNull() && dst.IsKnown() && dst.LengthInt() == 0
srcEmpty := !src.IsNull() && src.IsKnown() && src.LengthInt() == 0
if dst.IsNull() && !src.IsNull() && src.IsKnown() {
if src.LengthInt() == 0 {
return src
}
if (src.IsNull() && dstEmpty) || (srcEmpty && dst.IsNull()) {
return src
}
}
@ -1214,6 +1211,7 @@ func normalizeNullValues(dst, src cty.Value, apply bool) cty.Value {
}
dstVal = cty.NullVal(v.Type())
}
dstMap[key] = normalizeNullValues(dstVal, v, apply)
}

View File

@ -1141,6 +1141,41 @@ func TestNormalizeNullValues(t *testing.T) {
}),
}),
},
{
Src: cty.ObjectVal(map[string]cty.Value{
"set": cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{
"list": cty.List(cty.String),
}))),
}),
Dst: cty.ObjectVal(map[string]cty.Value{
"set": cty.SetValEmpty(cty.Object(map[string]cty.Type{
"list": cty.List(cty.String),
})),
}),
Expect: cty.ObjectVal(map[string]cty.Value{
"set": cty.SetValEmpty(cty.Object(map[string]cty.Type{
"list": cty.List(cty.String),
})),
}),
},
{
Src: cty.ObjectVal(map[string]cty.Value{
"set": cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{
"list": cty.List(cty.String),
}))),
}),
Dst: cty.ObjectVal(map[string]cty.Value{
"set": cty.SetValEmpty(cty.Object(map[string]cty.Type{
"list": cty.List(cty.String),
})),
}),
Expect: cty.ObjectVal(map[string]cty.Value{
"set": cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{
"list": cty.List(cty.String),
}))),
}),
Apply: true,
},
} {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
got := normalizeNullValues(tc.Dst, tc.Src, tc.Apply)