diff --git a/helper/schema/field_reader_map.go b/helper/schema/field_reader_map.go index d3ea401350..569cf9d915 100644 --- a/helper/schema/field_reader_map.go +++ b/helper/schema/field_reader_map.go @@ -56,8 +56,11 @@ func (r *MapFieldReader) readMap(k string) (FieldReadResult, error) { prefix := k + "." r.Map.Range(func(k, v string) bool { if strings.HasPrefix(k, prefix) { - result[k[len(prefix):]] = v - resultSet = true + key := k[len(prefix):] + if key != "#" { + result[key] = v + resultSet = true + } } return true diff --git a/helper/schema/field_reader_map_test.go b/helper/schema/field_reader_map_test.go index cd4f6b9564..ae4e69b5ea 100644 --- a/helper/schema/field_reader_map_test.go +++ b/helper/schema/field_reader_map_test.go @@ -28,6 +28,7 @@ func TestMapFieldReader(t *testing.T) { "listInt.0": "21", "listInt.1": "42", + "map.#": "2", "map.foo": "bar", "map.bar": "baz", diff --git a/helper/schema/field_writer_map.go b/helper/schema/field_writer_map.go index fd67963773..a9b38ac45c 100644 --- a/helper/schema/field_writer_map.go +++ b/helper/schema/field_writer_map.go @@ -170,6 +170,9 @@ func (w *MapFieldWriter) setMap( } } + // Set the count + w.result[k+".#"] = strconv.Itoa(len(vs)) + return nil } diff --git a/helper/schema/field_writer_map_test.go b/helper/schema/field_writer_map_test.go index fa2e2fa2b7..ea87e6734d 100644 --- a/helper/schema/field_writer_map_test.go +++ b/helper/schema/field_writer_map_test.go @@ -107,6 +107,7 @@ func TestMapFieldWriter(t *testing.T) { map[string]interface{}{"foo": "bar"}, false, map[string]string{ + "map.#": "1", "map.foo": "bar", }, }, diff --git a/helper/schema/resource_data_test.go b/helper/schema/resource_data_test.go index 92851c9bcc..fa0c18ca92 100644 --- a/helper/schema/resource_data_test.go +++ b/helper/schema/resource_data_test.go @@ -1641,8 +1641,10 @@ func TestResourceDataState(t *testing.T) { State: &terraform.InstanceState{ Attributes: map[string]string{ "config_vars.#": "2", + "config_vars.0.#": "2", "config_vars.0.foo": "bar", "config_vars.0.bar": "bar", + "config_vars.1.#": "1", "config_vars.1.bar": "baz", }, }, @@ -1669,7 +1671,9 @@ func TestResourceDataState(t *testing.T) { Result: &terraform.InstanceState{ Attributes: map[string]string{ "config_vars.#": "2", + "config_vars.0.#": "1", "config_vars.0.foo": "bar", + "config_vars.1.#": "1", "config_vars.1.baz": "bang", }, }, @@ -2094,8 +2098,10 @@ func TestResourceDataState(t *testing.T) { Attributes: map[string]string{ // TODO: broken, shouldn't bar be removed? "config_vars.#": "2", + "config_vars.0.#": "2", "config_vars.0.foo": "bar", "config_vars.0.bar": "bar", + "config_vars.1.#": "1", "config_vars.1.bar": "baz", }, }, @@ -2199,6 +2205,7 @@ func TestResourceDataState(t *testing.T) { Result: &terraform.InstanceState{ Attributes: map[string]string{ + "tags.#": "1", "tags.Name": "foo", }, }, @@ -2289,6 +2296,57 @@ func TestResourceDataState(t *testing.T) { }, }, }, + + // #23 Set of maps + { + Schema: map[string]*Schema{ + "ports": &Schema{ + Type: TypeSet, + Optional: true, + Computed: true, + Elem: &Resource{ + Schema: map[string]*Schema{ + "index": &Schema{Type: TypeInt}, + "uuids": &Schema{Type: TypeMap}, + }, + }, + Set: func(a interface{}) int { + m := a.(map[string]interface{}) + return m["index"].(int) + }, + }, + }, + + State: nil, + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "ports.10.uuids.#": &terraform.ResourceAttrDiff{ + NewComputed: true, + }, + }, + }, + + Set: map[string]interface{}{ + "ports": []interface{}{ + map[string]interface{}{ + "index": 10, + "uuids": map[string]interface{}{ + "80": "value", + }, + }, + }, + }, + + Result: &terraform.InstanceState{ + Attributes: map[string]string{ + "ports.#": "1", + "ports.10.index": "10", + "ports.10.uuids.#": "1", + "ports.10.uuids.80": "value", + }, + }, + }, } for i, tc := range cases { diff --git a/helper/schema/resource_test.go b/helper/schema/resource_test.go index 845bd264d6..3c378673b7 100644 --- a/helper/schema/resource_test.go +++ b/helper/schema/resource_test.go @@ -157,6 +157,7 @@ func TestResourceApply_destroyCreate(t *testing.T) { Attributes: map[string]string{ "id": "foo", "foo": "42", + "tags.#": "1", "tags.Name": "foo", }, }