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,21 +1668,28 @@ func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState {
// Remove any now empty array, maps or sets because a parent structure // Remove any now empty array, maps or sets because a parent structure
// won't include these entries in the count value. // won't include these entries in the count value.
isCount := regexp.MustCompile(`\.[%#]$`).MatchString isCount := regexp.MustCompile(`\.[%#]$`).MatchString
var deleted []string
for k, v := range result.Attributes { for k, v := range result.Attributes {
if isCount(k) && v == "0" { if isCount(k) && v == "0" {
delete(result.Attributes, k) delete(result.Attributes, k)
deleted = append(deleted, k)
}
}
for _, k := range deleted {
// Sanity check for invalid structures. // Sanity check for invalid structures.
// If we removed the primary count key, there should have been no // If we removed the primary count key, there should have been no
// other keys left with this prefix. // other keys left with this prefix.
base := k[:len(k)-2]
// this must have a "#" or "%" which we need to remove
base := k[:len(k)-1]
for k, _ := range result.Attributes { for k, _ := range result.Attributes {
if strings.HasPrefix(k, base) { if strings.HasPrefix(k, base) {
panic(fmt.Sprintf("empty structure %q has entry %q", base, k)) panic(fmt.Sprintf("empty structure %q has entry %q", base, k))
} }
} }
} }
}
return result return result
} }

View File

@ -1404,6 +1404,15 @@ func TestInstanceState_MergeDiffRemoveCounts(t *testing.T) {
"all.1234.0": "a", "all.1234.0": "a",
"all.5678.%": "1", "all.5678.%": "1",
"all.5678.key": "val", "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",
}, },
} }
@ -1435,6 +1444,7 @@ func TestInstanceState_MergeDiffRemoveCounts(t *testing.T) {
expected := map[string]string{ expected := map[string]string{
"all.#": "1", "all.#": "1",
"all.1111": "x", "all.1111": "x",
"all.nested_value": "y",
} }
if !reflect.DeepEqual(expected, is2.Attributes) { if !reflect.DeepEqual(expected, is2.Attributes) {