diff --git a/helper/schema/resource_data.go b/helper/schema/resource_data.go index cdc0d82d2..23be6f290 100644 --- a/helper/schema/resource_data.go +++ b/helper/schema/resource_data.go @@ -465,20 +465,27 @@ func (d *ResourceData) getMap( if !exact || level == getSourceSet { if d.setMap != nil && level >= getSourceSet { cleared := false - for k, _ := range d.setMap { - if !strings.HasPrefix(k, prefix) { - continue - } + if v, ok := d.setMap[k]; ok && v == "" { + // We've cleared the map + result = make(map[string]interface{}) resultSet = true + } else { + for k, _ := range d.setMap { + if !strings.HasPrefix(k, prefix) { + continue + } + resultSet = true - if !cleared { - // We clear the results if they are in the set map - result = make(map[string]interface{}) - cleared = true + if !cleared { + // We clear the results if they are in the set map + result = make(map[string]interface{}) + cleared = true + } + + single := k[len(prefix):] + result[single] = d.getPrimitive( + k, nil, elemSchema, source).Value } - - single := k[len(prefix):] - result[single] = d.getPrimitive(k, nil, elemSchema, source).Value } } } @@ -783,14 +790,6 @@ func (d *ResourceData) setMapValue( return fmt.Errorf("%s: full map must be set, no a single element", k) } - // Delete any prior map set - /* - v := d.getMap(k, nil, schema, getSourceSet) - for subKey, _ := range v.(map[string]interface{}) { - delete(d.setMap, fmt.Sprintf("%s.%s", k, subKey)) - } - */ - v := reflect.ValueOf(value) if v.Kind() != reflect.Map { return fmt.Errorf("%s: must be a map", k) @@ -804,6 +803,13 @@ func (d *ResourceData) setMapValue( vs[mk.String()] = mv.Interface() } + if len(vs) == 0 { + // The empty string here means the map is removed. + d.setMap[k] = "" + return nil + } + + delete(d.setMap, k) for subKey, v := range vs { err := d.set(fmt.Sprintf("%s.%s", k, subKey), nil, elemSchema, v) if err != nil { diff --git a/helper/schema/resource_data_test.go b/helper/schema/resource_data_test.go index d2cb38652..b71d441e8 100644 --- a/helper/schema/resource_data_test.go +++ b/helper/schema/resource_data_test.go @@ -2193,6 +2193,63 @@ func TestResourceDataState(t *testing.T) { }, }, }, + + // Maps + { + Schema: map[string]*Schema{ + "tags": &Schema{ + Type: TypeMap, + Optional: true, + Computed: true, + }, + }, + + State: nil, + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "tags.Name": &terraform.ResourceAttrDiff{ + Old: "", + New: "foo", + }, + }, + }, + + Result: &terraform.InstanceState{ + Attributes: map[string]string{ + "tags.Name": "foo", + }, + }, + }, + + { + Schema: map[string]*Schema{ + "tags": &Schema{ + Type: TypeMap, + Optional: true, + Computed: true, + }, + }, + + State: nil, + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "tags.Name": &terraform.ResourceAttrDiff{ + Old: "", + New: "foo", + }, + }, + }, + + Set: map[string]interface{}{ + "tags": map[string]string{}, + }, + + Result: &terraform.InstanceState{ + Attributes: map[string]string{}, + }, + }, } for i, tc := range cases {