From 89259a1b003b2d55595e28c6660ed0541d945dc0 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 20 Jan 2017 16:23:10 -0500 Subject: [PATCH] Fix the removal of empty containers from a flatmap Removal of empty nested containers from a flatmap would sometimes fail a sanity check when removed in the wrong order. This would only fail sometimes due to map iteration. There was also an off-by-one error in the prefix check which could match the incorrect keys. --- terraform/state.go | 23 +++++++++++++++-------- terraform/state_test.go | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/terraform/state.go b/terraform/state.go index f05ca4773..7acdd51a3 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -1668,18 +1668,25 @@ func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { // Remove any now empty array, maps or sets because a parent structure // won't include these entries in the count value. isCount := regexp.MustCompile(`\.[%#]$`).MatchString + var deleted []string + for k, v := range result.Attributes { if isCount(k) && v == "0" { delete(result.Attributes, k) + deleted = append(deleted, k) + } + } - // Sanity check for invalid structures. - // If we removed the primary count key, there should have been no - // other keys left with this prefix. - base := k[:len(k)-2] - for k, _ := range result.Attributes { - if strings.HasPrefix(k, base) { - panic(fmt.Sprintf("empty structure %q has entry %q", base, k)) - } + for _, k := range deleted { + // Sanity check for invalid structures. + // If we removed the primary count key, there should have been no + // other keys left with this prefix. + + // this must have a "#" or "%" which we need to remove + base := k[:len(k)-1] + for k, _ := range result.Attributes { + if strings.HasPrefix(k, base) { + panic(fmt.Sprintf("empty structure %q has entry %q", base, k)) } } } diff --git a/terraform/state_test.go b/terraform/state_test.go index c2591e633..d1a640cfc 100644 --- a/terraform/state_test.go +++ b/terraform/state_test.go @@ -1404,6 +1404,15 @@ func TestInstanceState_MergeDiffRemoveCounts(t *testing.T) { "all.1234.0": "a", "all.5678.%": "1", "all.5678.key": "val", + + // nested empty lists need to be removed cleanly + "all.nested.#": "0", + "all.nested.0.empty.#": "0", + "all.nested.1.empty.#": "0", + + // the value has a prefix that matches another key + // and ntohing should happen to this. + "all.nested_value": "y", }, } @@ -1433,8 +1442,9 @@ func TestInstanceState_MergeDiffRemoveCounts(t *testing.T) { is2 := is.MergeDiff(diff) expected := map[string]string{ - "all.#": "1", - "all.1111": "x", + "all.#": "1", + "all.1111": "x", + "all.nested_value": "y", } if !reflect.DeepEqual(expected, is2.Attributes) {