From 0b827ab6b6dec282b351dbd89b96595407f5dd33 Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Wed, 21 Jul 2021 08:51:35 -0400 Subject: [PATCH] format/diff: fix panic with null map in NestedType attrs (#29206) --- internal/command/format/diff.go | 6 ++++ internal/command/format/diff_test.go | 47 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/internal/command/format/diff.go b/internal/command/format/diff.go index da47b8f7c..b87b11c18 100644 --- a/internal/command/format/diff.go +++ b/internal/command/format/diff.go @@ -660,6 +660,12 @@ func (p *blockBodyDiffPrinter) writeNestedAttrDiff( p.buf.WriteString("]") case configschema.NestingMap: + // For the sake of handling nested blocks, we'll treat a null map + // the same as an empty map since the config language doesn't + // distinguish these anyway. + old = ctyNullBlockMapAsEmpty(old) + new = ctyNullBlockMapAsEmpty(new) + oldItems := old.AsValueMap() newItems := new.AsValueMap() diff --git a/internal/command/format/diff_test.go b/internal/command/format/diff_test.go index 1ab864b2a..2b4ece8d2 100644 --- a/internal/command/format/diff_test.go +++ b/internal/command/format/diff_test.go @@ -2869,6 +2869,53 @@ func TestResourceChange_nestedSet(t *testing.T) { func TestResourceChange_nestedMap(t *testing.T) { testCases := map[string]testCase{ + "creation from null": { + Action: plans.Update, + Mode: addrs.ManagedResourceMode, + Before: cty.ObjectVal(map[string]cty.Value{ + "id": cty.NullVal(cty.String), + "ami": cty.NullVal(cty.String), + "disks": cty.NullVal(cty.Map(cty.Object(map[string]cty.Type{ + "mount_point": cty.String, + "size": cty.String, + }))), + "root_block_device": cty.NullVal(cty.Map(cty.Object(map[string]cty.Type{ + "volume_type": cty.String, + }))), + }), + After: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("i-02ae66f368e8518a9"), + "ami": cty.StringVal("ami-AFTER"), + "disks": cty.MapVal(map[string]cty.Value{ + "disk_a": cty.ObjectVal(map[string]cty.Value{ + "mount_point": cty.StringVal("/var/diska"), + "size": cty.NullVal(cty.String), + }), + }), + "root_block_device": cty.MapVal(map[string]cty.Value{ + "a": cty.ObjectVal(map[string]cty.Value{ + "volume_type": cty.StringVal("gp2"), + }), + }), + }), + RequiredReplace: cty.NewPathSet(), + Schema: testSchema(configschema.NestingMap), + ExpectedOutput: ` # test_instance.example will be updated in-place + ~ resource "test_instance" "example" { + + ami = "ami-AFTER" + + disks = { + + "disk_a" = { + + mount_point = "/var/diska" + }, + } + + id = "i-02ae66f368e8518a9" + + + root_block_device "a" { + + volume_type = "gp2" + } + } +`, + }, "in-place update - creation": { Action: plans.Update, Mode: addrs.ManagedResourceMode,