From 77af322c1ce7bfc873734877f6312852b7c4207b Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 15 Oct 2020 21:21:14 -0400 Subject: [PATCH] handle non-null, but empty NestingMap in a set --- plans/objchange/objchange.go | 16 +++++---- plans/objchange/objchange_test.go | 55 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/plans/objchange/objchange.go b/plans/objchange/objchange.go index b833e85202..ab16f68a4b 100644 --- a/plans/objchange/objchange.go +++ b/plans/objchange/objchange.go @@ -333,8 +333,9 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo } for name, blockType := range schema.BlockTypes { - switch blockType.Nesting { + elementType := blockType.Block.ImpliedType() + switch blockType.Nesting { case configschema.NestingSingle, configschema.NestingGroup: attrs[name] = setElementCompareValue(&blockType.Block, v.GetAttr(name), isConfig) @@ -361,7 +362,7 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo attrs[name] = cty.SetVal(elems) // NestingList cases - case blockType.Block.ImpliedType().HasDynamicTypes(): + case elementType.HasDynamicTypes(): attrs[name] = cty.TupleVal(elems) default: attrs[name] = cty.ListVal(elems) @@ -369,19 +370,19 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo } else { switch { case blockType.Nesting == configschema.NestingSet: - attrs[name] = cty.SetValEmpty(blockType.Block.ImpliedType()) + attrs[name] = cty.SetValEmpty(elementType) // NestingList cases - case blockType.Block.ImpliedType().HasDynamicTypes(): + case elementType.HasDynamicTypes(): attrs[name] = cty.EmptyTupleVal default: - attrs[name] = cty.ListValEmpty(blockType.Block.ImpliedType()) + attrs[name] = cty.ListValEmpty(elementType) } } case configschema.NestingMap: cv := v.GetAttr(name) - if cv.IsNull() || !cv.IsKnown() { + if cv.IsNull() || !cv.IsKnown() || cv.LengthInt() == 0 { attrs[name] = cv continue } @@ -390,8 +391,9 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo kv, ev := it.Element() elems[kv.AsString()] = setElementCompareValue(&blockType.Block, ev, isConfig) } + switch { - case blockType.Block.ImpliedType().HasDynamicTypes(): + case elementType.HasDynamicTypes(): attrs[name] = cty.ObjectVal(elems) default: attrs[name] = cty.MapVal(elems) diff --git a/plans/objchange/objchange_test.go b/plans/objchange/objchange_test.go index d6352337be..065e4add88 100644 --- a/plans/objchange/objchange_test.go +++ b/plans/objchange/objchange_test.go @@ -799,6 +799,61 @@ func TestProposedNewObject(t *testing.T) { }), }), }, + "empty nested map in set": { + &configschema.Block{ + BlockTypes: map[string]*configschema.NestedBlock{ + "foo": { + Nesting: configschema.NestingSet, + Block: configschema.Block{ + BlockTypes: map[string]*configschema.NestedBlock{ + "bar": { + Nesting: configschema.NestingMap, + Block: configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.String, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.MapValEmpty(cty.Object(map[string]cty.Type{ + "baz": cty.String, + })), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.MapVal(map[string]cty.Value{ + "bing": cty.ObjectVal(map[string]cty.Value{ + "baz": cty.StringVal("true"), + }), + }), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.MapVal(map[string]cty.Value{ + "bing": cty.ObjectVal(map[string]cty.Value{ + "baz": cty.StringVal("true"), + }), + }), + }), + }), + }), + }, } for name, test := range tests {