diff --git a/builtin/providers/test/resource_computed_set.go b/builtin/providers/test/resource_computed_set.go index 09b49d420..092cd2276 100644 --- a/builtin/providers/test/resource_computed_set.go +++ b/builtin/providers/test/resource_computed_set.go @@ -70,6 +70,12 @@ func testResourceComputedSet() *schema.Resource { }, }, }, + "optional_set": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, }, } } @@ -101,6 +107,9 @@ func testResourceComputedSetRead(d *schema.ResourceData, meta interface{}) error } d.Set("string_set", schema.NewSet(schema.HashString, set)) + + // This isn't computed, but we should be able to ignore without issues. + d.Set("optional_set", []interface{}{}) return nil } diff --git a/builtin/providers/test/resource_list.go b/builtin/providers/test/resource_list.go index 32d4c9da0..a3d01b79e 100644 --- a/builtin/providers/test/resource_list.go +++ b/builtin/providers/test/resource_list.go @@ -75,6 +75,36 @@ func testResourceList() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + + "never_set": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sublist": { + Type: schema.TypeList, + MaxItems: 1, + ForceNew: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "bool": { + Type: schema.TypeBool, + ForceNew: true, + Required: true, + }, + "string": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, }, } } @@ -101,10 +131,21 @@ func testResourceListRead(d *schema.ResourceData, meta interface{}) error { return err } + // "computing" these values should insert empty containers into the + // never_set block. + values := make(map[string]interface{}) + values["sublist"] = []interface{}{} + d.Set("never_set", []interface{}{values}) + return nil } func testResourceListUpdate(d *schema.ResourceData, meta interface{}) error { + block := d.Get("never_set").([]interface{}) + if len(block) > 0 { + // if profiles contains any values, they should not be nil + _ = block[0].(map[string]interface{}) + } return testResourceListRead(d, meta) } diff --git a/helper/plugin/grpc_provider.go b/helper/plugin/grpc_provider.go index 1b046f9d9..b8dacc9bf 100644 --- a/helper/plugin/grpc_provider.go +++ b/helper/plugin/grpc_provider.go @@ -798,7 +798,6 @@ func (s *GRPCProviderServer) ApplyResourceChange(_ context.Context, req *proto.A if err != nil { resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err) } - newStateVal := cty.NullVal(block.ImpliedType()) // Always return a null value for destroy. @@ -1114,8 +1113,6 @@ func normalizeFlatmapContainers(prior map[string]string, attrs map[string]string attrs[k] = "1" case len(indexes) > 0: attrs[k] = strconv.Itoa(len(indexes)) - default: - delete(attrs, k) } } diff --git a/helper/plugin/grpc_provider_test.go b/helper/plugin/grpc_provider_test.go index 650c1e7b9..cf0b805fa 100644 --- a/helper/plugin/grpc_provider_test.go +++ b/helper/plugin/grpc_provider_test.go @@ -671,29 +671,21 @@ func TestNormalizeFlatmapContainers(t *testing.T) { attrs map[string]string expect map[string]string }{ - { - attrs: map[string]string{"id": "1", "multi.2.set.#": "1", "multi.1.set.#": "0", "single.#": "0"}, - expect: map[string]string{"id": "1", "multi.2.set.#": "1"}, - }, { attrs: map[string]string{"id": "1", "multi.2.set.#": "2", "multi.2.set.1.foo": "bar", "multi.1.set.#": "0", "single.#": "0"}, - expect: map[string]string{"id": "1", "multi.2.set.#": "1", "multi.2.set.1.foo": "bar"}, + expect: map[string]string{"id": "1", "multi.2.set.#": "1", "multi.2.set.1.foo": "bar", "multi.1.set.#": "0", "single.#": "0"}, }, { attrs: map[string]string{"id": "78629a0f5f3f164f", "multi.#": "1"}, expect: map[string]string{"id": "78629a0f5f3f164f", "multi.#": "1"}, }, - { - attrs: map[string]string{"id": "78629a0f5f3f164f", "multi.#": "0"}, - expect: map[string]string{"id": "78629a0f5f3f164f"}, - }, { attrs: map[string]string{"multi.529860700.set.#": "0", "multi.#": "1", "id": "78629a0f5f3f164f"}, - expect: map[string]string{"id": "78629a0f5f3f164f", "multi.#": "1"}, + expect: map[string]string{"multi.529860700.set.#": "0", "multi.#": "1", "id": "78629a0f5f3f164f"}, }, { attrs: map[string]string{"set.2.required": "bar", "set.2.list.#": "1", "set.2.list.0": "x", "set.1.list.#": "0", "set.#": "2"}, - expect: map[string]string{"set.2.list.#": "1", "set.2.list.0": "x", "set.2.required": "bar", "set.#": "1"}, + expect: map[string]string{"set.2.required": "bar", "set.2.list.#": "1", "set.2.list.0": "x", "set.1.list.#": "0", "set.#": "2"}, }, { attrs: map[string]string{"map.%": hcl2shim.UnknownVariableValue, "list.#": hcl2shim.UnknownVariableValue, "id": "1"}, @@ -702,7 +694,7 @@ func TestNormalizeFlatmapContainers(t *testing.T) { { prior: map[string]string{"map.%": "0"}, attrs: map[string]string{"map.%": "0", "list.#": "0", "id": "1"}, - expect: map[string]string{"id": "1", "map.%": "0"}, + expect: map[string]string{"id": "1", "list.#": "0", "map.%": "0"}, }, { prior: map[string]string{"map.%": hcl2shim.UnknownVariableValue, "list.#": "0"}, @@ -712,7 +704,7 @@ func TestNormalizeFlatmapContainers(t *testing.T) { { prior: map[string]string{"list.#": "1", "list.0": "old value"}, attrs: map[string]string{"list.#": "0"}, - expect: map[string]string{}, + expect: map[string]string{"list.#": "0"}, }, } { t.Run(strconv.Itoa(i), func(t *testing.T) {