helper/schema: write "attr.#": "0" for empty maps

This fixes some perpetual diffs I saw in Atlas AccTests where an empty
map (`map[string]interface{}{}`) was being `d.Set` for "metadata_full".

Because the MapFieldWriter was not distinguishing between empty and nil,
this trigger the "map delete" logic and no count was written to the
state. This caused subsequent plans to improperly report a diff.

Here we redefine the map delete functionality to explicitly trigger only
on `nil`, so we catch the `.#` field for empty maps.
This commit is contained in:
Paul Hinze 2015-05-06 10:21:22 -05:00
parent 010a39a58e
commit f2368428d3
2 changed files with 15 additions and 15 deletions

View File

@ -141,25 +141,23 @@ func (w *MapFieldWriter) setMap(
v := reflect.ValueOf(value)
vs := make(map[string]interface{})
if value != nil {
if v.Kind() != reflect.Map {
return fmt.Errorf("%s: must be a map", k)
}
if v.Type().Key().Kind() != reflect.String {
return fmt.Errorf("%s: keys must strings", k)
}
for _, mk := range v.MapKeys() {
mv := v.MapIndex(mk)
vs[mk.String()] = mv.Interface()
}
}
if len(vs) == 0 {
if value == nil {
// The empty string here means the map is removed.
w.result[k] = ""
return nil
}
if v.Kind() != reflect.Map {
return fmt.Errorf("%s: must be a map", k)
}
if v.Type().Key().Kind() != reflect.String {
return fmt.Errorf("%s: keys must strings", k)
}
for _, mk := range v.MapKeys() {
mv := v.MapIndex(mk)
vs[mk.String()] = mv.Interface()
}
// Remove the pure key since we're setting the full map value
delete(w.result, k)

View File

@ -2539,7 +2539,9 @@ func TestResourceDataState(t *testing.T) {
},
Result: &terraform.InstanceState{
Attributes: map[string]string{},
Attributes: map[string]string{
"tags.#": "0",
},
},
},