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.
This commit is contained in:
James Bardin 2017-01-20 16:23:10 -05:00
parent 60e4cfd285
commit 89259a1b00
2 changed files with 27 additions and 10 deletions

View File

@ -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))
}
}
}

View File

@ -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) {