diff --git a/builtin/providers/test/resource_list_set.go b/builtin/providers/test/resource_list_set.go index 6e8390364..0ce5abc8d 100644 --- a/builtin/providers/test/resource_list_set.go +++ b/builtin/providers/test/resource_list_set.go @@ -50,6 +50,125 @@ func testResourceListSet() *schema.Resource { }, }, }, + "replication_configuration": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "role": { + Type: schema.TypeString, + Required: true, + }, + "rules": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + }, + "destination": { + Type: schema.TypeSet, + MaxItems: 1, + MinItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_id": { + Type: schema.TypeString, + Optional: true, + }, + "bucket": { + Type: schema.TypeString, + Required: true, + }, + "storage_class": { + Type: schema.TypeString, + Optional: true, + }, + "replica_kms_key_id": { + Type: schema.TypeString, + Optional: true, + }, + "access_control_translation": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "owner": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + }, + }, + }, + "source_selection_criteria": { + Type: schema.TypeSet, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sse_kms_encrypted_objects": { + Type: schema.TypeSet, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + }, + }, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + }, + "status": { + Type: schema.TypeString, + Required: true, + }, + "priority": { + Type: schema.TypeInt, + Optional: true, + }, + "filter": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "prefix": { + Type: schema.TypeString, + Optional: true, + }, + "tags": { + Type: schema.TypeMap, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, }, } } diff --git a/builtin/providers/test/resource_list_set_test.go b/builtin/providers/test/resource_list_set_test.go index 11cb742e8..f1e8353fb 100644 --- a/builtin/providers/test/resource_list_set_test.go +++ b/builtin/providers/test/resource_list_set_test.go @@ -53,3 +53,66 @@ resource "test_resource_list_set" "foo" { }, }) } + +func TestResourceListSet_updateNested(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_list_set" "foo" { + replication_configuration { + role = "role_id" + rules { + id = "foobar" + status = "Enabled" + priority = 42 + filter { + tags = { + ReplicateMe = "Yes" + } + } + destination { + bucket = "bucket_id" + storage_class = "STANDARD" + } + } + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("test_resource_list_set.foo", "replication_configuration.0.rules.#", "1"), + ), + }, + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_list_set" "foo" { + replication_configuration { + role = "role_id" + rules { + id = "foobar" + status = "Enabled" + priority = 42 + filter { + prefix = "foo" + tags = { + ReplicateMe = "Yes" + AnotherTag = "OK" + } + } + destination { + bucket = "bucket_id" + storage_class = "STANDARD" + } + } + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("test_resource_list_set.foo", "replication_configuration.0.rules.#", "1"), + ), + }, + }, + }) +} diff --git a/helper/plugin/grpc_provider.go b/helper/plugin/grpc_provider.go index 1504fad91..8a4f253c5 100644 --- a/helper/plugin/grpc_provider.go +++ b/helper/plugin/grpc_provider.go @@ -498,6 +498,12 @@ func (s *GRPCProviderServer) PlanResourceChange(_ context.Context, req *proto.Pl return resp, nil } + // We don't usually plan destroys, but this can return early in any case. + if proposedNewStateVal.IsNull() { + resp.PlannedState = req.ProposedNewState + return resp, nil + } + info := &terraform.InstanceInfo{ Type: req.TypeName, } diff --git a/terraform/diff.go b/terraform/diff.go index f87db081f..e68f3d81e 100644 --- a/terraform/diff.go +++ b/terraform/diff.go @@ -546,7 +546,7 @@ func (d *InstanceDiff) applyBlockDiff(path []string, attrs map[string]string, sc } // check for empty "count" keys - if strings.HasSuffix(attr, ".#") && diff.New == "0" { + if (strings.HasSuffix(attr, ".#") || strings.HasSuffix(attr, ".%")) && diff.New == "0" { continue }