From 40174b634ac54e3f4926ede57e642a346740d780 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 11 Nov 2021 10:15:29 -0500 Subject: [PATCH 1/2] ignore_changes changing a null map to empty Fix an error where using `ignore_changes` would cause some null maps to be saved as an empty map. --- internal/terraform/node_resource_abstract_instance.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index 3cab2b181a..b7b781191b 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -1289,10 +1289,15 @@ func processIgnoreChangesIndividual(prior, config cty.Value, ignoreChangesPath [ } var newVal cty.Value - if len(configMap) == 0 { - newVal = cty.MapValEmpty(v.Type().ElementType()) - } else { + switch { + case len(configMap) > 0: newVal = cty.MapVal(configMap) + case v.IsNull(): + // if the config value was null, and no values remain in the map, + // reset the value to null. + newVal = v + default: + newVal = cty.MapValEmpty(v.Type().ElementType()) } if len(vMarks) > 0 { From 9d19086c8eeef6b8ca5275f8d18d45033d81ed48 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 11 Nov 2021 10:42:36 -0500 Subject: [PATCH 2/2] test for null map and fix lost map marks Add a test to ensure ignore_changes does not change null maps to empty maps. Fix when a marked map revers the changes ignored within that map. --- .../node_resource_abstract_instance.go | 2 +- internal/terraform/reduce_plan_test.go | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index b7b781191b..d2b6489be3 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -1301,7 +1301,7 @@ func processIgnoreChangesIndividual(prior, config cty.Value, ignoreChangesPath [ } if len(vMarks) > 0 { - newVal = v.WithMarks(vMarks) + newVal = newVal.WithMarks(vMarks) } return newVal, nil diff --git a/internal/terraform/reduce_plan_test.go b/internal/terraform/reduce_plan_test.go index 2d134d2c28..f32101aaf5 100644 --- a/internal/terraform/reduce_plan_test.go +++ b/internal/terraform/reduce_plan_test.go @@ -369,6 +369,54 @@ func TestProcessIgnoreChangesIndividual(t *testing.T) { "b": cty.StringVal("new b value"), }), }, + "null_map": { + cty.ObjectVal(map[string]cty.Value{ + "a": cty.StringVal("ok"), + "list": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "s": cty.StringVal("ok"), + "map": cty.NullVal(cty.Map(cty.String)), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "a": cty.NullVal(cty.String), + "list": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "s": cty.StringVal("ok"), + "map": cty.NullVal(cty.Map(cty.String)), + }), + }), + }), + []string{"a"}, + cty.ObjectVal(map[string]cty.Value{ + "a": cty.StringVal("ok"), + "list": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "s": cty.StringVal("ok"), + "map": cty.NullVal(cty.Map(cty.String)), + }), + }), + }), + }, + "marked_map": { + cty.ObjectVal(map[string]cty.Value{ + "map": cty.MapVal(map[string]cty.Value{ + "key": cty.StringVal("val"), + }).Mark("marked"), + }), + cty.ObjectVal(map[string]cty.Value{ + "map": cty.MapVal(map[string]cty.Value{ + "key": cty.StringVal("new val"), + }).Mark("marked"), + }), + []string{`map["key"]`}, + cty.ObjectVal(map[string]cty.Value{ + "map": cty.MapVal(map[string]cty.Value{ + "key": cty.StringVal("val"), + }).Mark("marked"), + }), + }, } for name, test := range tests {