From 2789d3853d4b7e0159cdfb45a77089731861f8d4 Mon Sep 17 00:00:00 2001 From: Shawn Chasse Date: Tue, 5 Sep 2023 14:30:54 -0400 Subject: [PATCH 01/15] Revert bad commit --- .../drt_access_log_bucket_association.go | 292 ++++++++++++++ .../drt_access_log_bucket_association_test.go | 292 ++++++++++++++ .../shield/drt_access_role_arn_association.go | 359 ++++++++++++++++++ .../drt_access_role_arn_association_test.go | 179 +++++++++ internal/service/shield/exports_test.go | 10 + .../service/shield/service_package_gen.go | 11 +- ...ccess_log_bucket_association.html.markdown | 35 ++ ..._access_role_arn_association.html.markdown | 51 +++ 8 files changed, 1228 insertions(+), 1 deletion(-) create mode 100644 internal/service/shield/drt_access_log_bucket_association.go create mode 100644 internal/service/shield/drt_access_log_bucket_association_test.go create mode 100644 internal/service/shield/drt_access_role_arn_association.go create mode 100644 internal/service/shield/drt_access_role_arn_association_test.go create mode 100644 internal/service/shield/exports_test.go create mode 100644 website/docs/r/shield_drt_access_log_bucket_association.html.markdown create mode 100644 website/docs/r/shield_drt_access_role_arn_association.html.markdown diff --git a/internal/service/shield/drt_access_log_bucket_association.go b/internal/service/shield/drt_access_log_bucket_association.go new file mode 100644 index 00000000000..8af1b75f8a6 --- /dev/null +++ b/internal/service/shield/drt_access_log_bucket_association.go @@ -0,0 +1,292 @@ +package shield_test + +import ( + "context" + "errors" + "fmt" + + //"regexp" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/shield/types" + "github.com/aws/aws-sdk-go/service/shield" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/names" + + tfshield "github.com/hashicorp/terraform-provider-aws/internal/service/shield" +) + +func TestAccShieldDRTAccessLogBucketAssociation_basic(t *testing.T) { + ctx := acctest.Context(t) + + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_shield_drt_access_log_bucket_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckLogBucket(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), + Check: testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), + }, + }, + }) +} + +func TestAccShieldDRTAccessLogBucketAssociation_multibucket(t *testing.T) { + ctx := acctest.Context(t) + + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var buckets = []string{} + for i := 0; i < 2; i++ { + buckets = append(buckets, sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)) + } + resourceName1 := "aws_shield_drt_access_log_bucket_association.test1" + resourceName2 := "aws_shield_drt_access_log_bucket_association.test2" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckLogBucket(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessLogBucketAssociationConfig_multibucket(rName, buckets, t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName1, &drtaccesslogbucketassociation, t), + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName2, &drtaccesslogbucketassociation, t), + ), + }, + }, + }) +} + +func TestAccShieldDRTAccessLogBucketAssociation_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_shield_drt_access_log_bucket_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckLogBucket(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfshield.ResourceDRTAccessLogBucketAssociation, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context, t *testing.T) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_shield_drt_access_log_bucket_association" { + continue + } + + input := &shield.DescribeDRTAccessInput{} + resp, err := conn.DescribeDRTAccessWithContext(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil + } + if err != nil { + return nil + } + if resp != nil { + if resp.LogBucketList != nil && len(resp.LogBucketList) > 0 { + for _, bucket := range resp.LogBucketList { + + if *bucket == rs.Primary.Attributes["log_bucket"] { + return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, errors.New("bucket association not destroyed")) + } + } + + } + return nil + } + + return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckDRTAccessLogBucketAssociationExists(ctx context.Context, name string, drtaccesslogbucketassociation *shield.DescribeDRTAccessOutput, t *testing.T) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + + if !ok { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + resp, err := conn.DescribeDRTAccessWithContext(ctx, &shield.DescribeDRTAccessInput{}) + if err != nil { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, err) + } + + *drtaccesslogbucketassociation = *resp + + return nil + } +} + +func testAccPreCheckLogBucket(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + + input := &shield.DescribeDRTAccessInput{} + _, err := conn.DescribeDRTAccessWithContext(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccDRTAccessLogBucketAssociationConfig_basic(rName string, bucket string, t *testing.T) string { + + return fmt.Sprintf(` + resource "aws_s3_bucket" "test" { + bucket = %[2]q + } + + resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "drt.shield.amazonaws.com" + }, + "Action": "sts:AssumeRole" + }, + ] + }) + } + + resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" + } + + resource "aws_shield_protection_group" "test" { + protection_group_id = %[1]q + aggregation = "MAX" + pattern = "ALL" + } + + resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn + } + + resource "aws_shield_drt_access_log_bucket_association" "test" { + log_bucket = aws_s3_bucket.test.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + } +`, rName, bucket) +} + +func testAccDRTAccessLogBucketAssociationConfig_multibucket(rName string, buckets []string, t *testing.T) string { + + return fmt.Sprintf(` + resource "aws_s3_bucket" "test1" { + bucket = %[2]q + } + resource "aws_s3_bucket" "test2" { + bucket = %[3]q + } + + resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "drt.shield.amazonaws.com" + }, + "Action": "sts:AssumeRole" + }, + ] + }) + } + + resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" + } + + resource "aws_shield_protection_group" "test" { + protection_group_id = %[1]q + aggregation = "MAX" + pattern = "ALL" + } + + resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn + } + + resource "aws_shield_drt_access_log_bucket_association" "test1" { + log_bucket = aws_s3_bucket.test1.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + } + resource "aws_shield_drt_access_log_bucket_association" "test2" { + log_bucket = aws_s3_bucket.test2.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + depends_on = [ + aws_shield_drt_access_log_bucket_association.test1 + ] + } +`, rName, buckets[0], buckets[1]) +} diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go new file mode 100644 index 00000000000..8af1b75f8a6 --- /dev/null +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -0,0 +1,292 @@ +package shield_test + +import ( + "context" + "errors" + "fmt" + + //"regexp" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/shield/types" + "github.com/aws/aws-sdk-go/service/shield" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/names" + + tfshield "github.com/hashicorp/terraform-provider-aws/internal/service/shield" +) + +func TestAccShieldDRTAccessLogBucketAssociation_basic(t *testing.T) { + ctx := acctest.Context(t) + + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_shield_drt_access_log_bucket_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckLogBucket(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), + Check: testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), + }, + }, + }) +} + +func TestAccShieldDRTAccessLogBucketAssociation_multibucket(t *testing.T) { + ctx := acctest.Context(t) + + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var buckets = []string{} + for i := 0; i < 2; i++ { + buckets = append(buckets, sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)) + } + resourceName1 := "aws_shield_drt_access_log_bucket_association.test1" + resourceName2 := "aws_shield_drt_access_log_bucket_association.test2" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckLogBucket(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessLogBucketAssociationConfig_multibucket(rName, buckets, t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName1, &drtaccesslogbucketassociation, t), + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName2, &drtaccesslogbucketassociation, t), + ), + }, + }, + }) +} + +func TestAccShieldDRTAccessLogBucketAssociation_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_shield_drt_access_log_bucket_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckLogBucket(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfshield.ResourceDRTAccessLogBucketAssociation, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context, t *testing.T) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_shield_drt_access_log_bucket_association" { + continue + } + + input := &shield.DescribeDRTAccessInput{} + resp, err := conn.DescribeDRTAccessWithContext(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil + } + if err != nil { + return nil + } + if resp != nil { + if resp.LogBucketList != nil && len(resp.LogBucketList) > 0 { + for _, bucket := range resp.LogBucketList { + + if *bucket == rs.Primary.Attributes["log_bucket"] { + return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, errors.New("bucket association not destroyed")) + } + } + + } + return nil + } + + return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckDRTAccessLogBucketAssociationExists(ctx context.Context, name string, drtaccesslogbucketassociation *shield.DescribeDRTAccessOutput, t *testing.T) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + + if !ok { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + resp, err := conn.DescribeDRTAccessWithContext(ctx, &shield.DescribeDRTAccessInput{}) + if err != nil { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, err) + } + + *drtaccesslogbucketassociation = *resp + + return nil + } +} + +func testAccPreCheckLogBucket(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + + input := &shield.DescribeDRTAccessInput{} + _, err := conn.DescribeDRTAccessWithContext(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccDRTAccessLogBucketAssociationConfig_basic(rName string, bucket string, t *testing.T) string { + + return fmt.Sprintf(` + resource "aws_s3_bucket" "test" { + bucket = %[2]q + } + + resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "drt.shield.amazonaws.com" + }, + "Action": "sts:AssumeRole" + }, + ] + }) + } + + resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" + } + + resource "aws_shield_protection_group" "test" { + protection_group_id = %[1]q + aggregation = "MAX" + pattern = "ALL" + } + + resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn + } + + resource "aws_shield_drt_access_log_bucket_association" "test" { + log_bucket = aws_s3_bucket.test.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + } +`, rName, bucket) +} + +func testAccDRTAccessLogBucketAssociationConfig_multibucket(rName string, buckets []string, t *testing.T) string { + + return fmt.Sprintf(` + resource "aws_s3_bucket" "test1" { + bucket = %[2]q + } + resource "aws_s3_bucket" "test2" { + bucket = %[3]q + } + + resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "drt.shield.amazonaws.com" + }, + "Action": "sts:AssumeRole" + }, + ] + }) + } + + resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" + } + + resource "aws_shield_protection_group" "test" { + protection_group_id = %[1]q + aggregation = "MAX" + pattern = "ALL" + } + + resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn + } + + resource "aws_shield_drt_access_log_bucket_association" "test1" { + log_bucket = aws_s3_bucket.test1.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + } + resource "aws_shield_drt_access_log_bucket_association" "test2" { + log_bucket = aws_s3_bucket.test2.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + depends_on = [ + aws_shield_drt_access_log_bucket_association.test1 + ] + } +`, rName, buckets[0], buckets[1]) +} diff --git a/internal/service/shield/drt_access_role_arn_association.go b/internal/service/shield/drt_access_role_arn_association.go new file mode 100644 index 00000000000..0c1da5254dc --- /dev/null +++ b/internal/service/shield/drt_access_role_arn_association.go @@ -0,0 +1,359 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package shield + +import ( + "context" + "errors" + "regexp" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go/service/shield" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// Function annotations are used for resource registration to the Provider. DO NOT EDIT. +// @FrameworkResource(name="DRT Access Role ARN Association") +func newResourceDRTAccessRoleARNAssociation(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceDRTAccessRoleARNAssociation{} + + r.SetDefaultCreateTimeout(30 * time.Minute) + r.SetDefaultUpdateTimeout(30 * time.Minute) + r.SetDefaultDeleteTimeout(30 * time.Minute) + + return r, nil +} + +const ( + ResNameDRTAccessRoleARNAssociation = "DRT Access Role ARN Association" +) + +type resourceDRTAccessRoleARNAssociation struct { + framework.ResourceWithConfigure + framework.WithTimeouts +} + +func (r *resourceDRTAccessRoleARNAssociation) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_shield_drt_access_role_arn_association" +} + +func (r *resourceDRTAccessRoleARNAssociation) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ // required by hashicorps terraform plugin testing framework + DeprecationMessage: "id is only for framework compatibility and not used by the provider", + MarkdownDescription: "The ID of the directory.", + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "role_arn": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 2048), + stringvalidator.RegexMatches( + regexp.MustCompile(`^arn:?[a-zA-Z\-]+:iam::\d{12}:role/?[a-zA-Z_0-9+=,.@\-_/]+`), + "must match arn pattern", + ), + }, + }, + }, + Blocks: map[string]schema.Block{ + "timeouts": timeouts.Block(ctx, timeouts.Opts{ + Create: true, + Delete: true, + Read: true, + }), + }, + } +} + +func (r *resourceDRTAccessRoleARNAssociation) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().ShieldConn(ctx) + + var plan resourceDRTAccessRoleARNAssociationData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + in := &shield.AssociateDRTRoleInput{ + RoleArn: aws.String(plan.RoleARN.ValueString()), + } + + out, err := conn.AssociateDRTRoleWithContext(ctx, in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionCreating, ResNameDRTAccessRoleARNAssociation, plan.RoleARN.String(), err), + err.Error(), + ) + return + } + if out == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionCreating, ResNameDRTAccessRoleARNAssociation, plan.RoleARN.String(), nil), + errors.New("empty output").Error(), + ) + return + } + + createTimeout := r.CreateTimeout(ctx, plan.Timeouts) + _, err = waitDRTAccessRoleARNAssociationCreated(ctx, conn, plan.RoleARN.ValueString(), createTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionWaitingForCreation, ResNameDRTAccessRoleARNAssociation, plan.RoleARN.String(), err), + err.Error(), + ) + return + } + + plan.ID = types.StringValue(plan.RoleARN.ValueString()) + + resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) +} + +func (r *resourceDRTAccessRoleARNAssociation) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().ShieldConn(ctx) + + var state resourceDRTAccessRoleARNAssociationData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + in := &shield.DescribeDRTAccessInput{} + out, err := conn.DescribeDRTAccessWithContext(ctx, in) + + if tfresource.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionSetting, ResNameDRTAccessRoleARNAssociation, state.RoleARN.String(), err), + err.Error(), + ) + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + // Setting ID of state - required by hashicorps terraform plugin testing framework for Import. See issue https://github.com/hashicorp/terraform-plugin-testing/issues/84 + state.ID = types.StringValue(state.RoleARN.ValueString()) + } + + state.RoleARN = flex.StringToFramework(ctx, out.RoleArn) + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceDRTAccessRoleARNAssociation) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().ShieldConn(ctx) + + // TIP: -- 2. Fetch the plan + var plan, state resourceDRTAccessRoleARNAssociationData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + if !plan.RoleARN.Equal(state.RoleARN) { + in := &shield.AssociateDRTRoleInput{ + RoleArn: aws.String(plan.RoleARN.ValueString()), + } + + out, err := conn.AssociateDRTRoleWithContext(ctx, in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionUpdating, ResNameDRTAccessRoleARNAssociation, plan.RoleARN.String(), err), + err.Error(), + ) + return + } + if out == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionUpdating, ResNameDRTAccessRoleARNAssociation, plan.RoleARN.String(), nil), + errors.New("empty output").Error(), + ) + return + } + } + + updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) + _, err := waitDRTAccessRoleARNAssociationUpdated(ctx, conn, plan.RoleARN.ValueString(), updateTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionWaitingForUpdate, ResNameDRTAccessRoleARNAssociation, plan.RoleARN.String(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *resourceDRTAccessRoleARNAssociation) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().ShieldConn(ctx) + + var state resourceDRTAccessRoleARNAssociationData + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + in := &shield.DisassociateDRTRoleInput{} + + _, err := conn.DisassociateDRTRoleWithContext(ctx, in) + if err != nil { + var nfe *shield.ResourceNotFoundException + if errors.As(err, &nfe) { + return + } + + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionDeleting, ResNameDRTAccessRoleARNAssociation, state.RoleARN.String(), err), + err.Error(), + ) + return + } + + deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) + _, err = waitDRTAccessRoleARNAssociationDeleted(ctx, conn, state.RoleARN.ValueString(), deleteTimeout) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionWaitingForDeletion, ResNameDRTAccessRoleARNAssociation, state.RoleARN.String(), err), + err.Error(), + ) + return + } +} + +func waitDRTAccessRoleARNAssociationCreated(ctx context.Context, conn *shield.Shield, roleARN string, timeout time.Duration) (*shield.DescribeDRTAccessOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{}, + Target: []string{statusNormal}, + Refresh: statusDRTAccessRoleARNAssociation(ctx, conn, roleARN), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*shield.DescribeDRTAccessOutput); ok { + return out, err + } + + return nil, err +} + +func waitDRTAccessRoleARNAssociationUpdated(ctx context.Context, conn *shield.Shield, roleARN string, timeout time.Duration) (*shield.DescribeDRTAccessOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{statusChangePending}, + Target: []string{statusUpdated}, + Refresh: statusDRTAccessRoleARNAssociation(ctx, conn, roleARN), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*shield.DescribeDRTAccessOutput); ok { + return out, err + } + + return nil, err +} + +func waitDRTAccessRoleARNAssociationDeleted(ctx context.Context, conn *shield.Shield, roleARN string, timeout time.Duration) (*shield.DescribeDRTAccessOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{statusDeleting, statusNormal}, + Target: []string{}, + Refresh: statusDRTAccessRoleARNAssociationDeleted(ctx, conn, roleARN), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if out, ok := outputRaw.(*shield.DescribeDRTAccessOutput); ok { + return out, err + } + + return nil, err +} + +func statusDRTAccessRoleARNAssociation(ctx context.Context, conn *shield.Shield, roleARN string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := describeDRTAccessRoleARNAssociation(ctx, conn, roleARN) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return out, statusNormal, nil + } +} + +func statusDRTAccessRoleARNAssociationDeleted(ctx context.Context, conn *shield.Shield, roleARN string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := describeDRTAccessRoleARNAssociation(ctx, conn, roleARN) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + if out.RoleArn != nil && aws.ToString(out.RoleArn) == roleARN { + return out, statusDeleting, nil + } + + return out, statusDeleting, nil + } +} + +func describeDRTAccessRoleARNAssociation(ctx context.Context, conn *shield.Shield, roleARN string) (*shield.DescribeDRTAccessOutput, error) { + in := &shield.DescribeDRTAccessInput{} + + out, err := conn.DescribeDRTAccessWithContext(ctx, in) + if err != nil { + var nfe *shield.ResourceNotFoundException + if errors.As(err, &nfe) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + } + + if out == nil || out.RoleArn == nil || aws.ToString(out.RoleArn) != roleARN { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +type resourceDRTAccessRoleARNAssociationData struct { + ID types.String `tfsdk:"id"` + RoleARN types.String `tfsdk:"role_arn"` + Timeouts timeouts.Value `tfsdk:"timeouts"` +} diff --git a/internal/service/shield/drt_access_role_arn_association_test.go b/internal/service/shield/drt_access_role_arn_association_test.go new file mode 100644 index 00000000000..0c995501923 --- /dev/null +++ b/internal/service/shield/drt_access_role_arn_association_test.go @@ -0,0 +1,179 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package shield_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/shield" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + tfshield "github.com/hashicorp/terraform-provider-aws/internal/service/shield" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// Acceptance test access AWS and cost money to run. +func TestAccShieldDRTAccessRoleARNAssociation_basic(t *testing.T) { + ctx := acctest.Context(t) + + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var drtaccessrolearnassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_shield_drt_access_role_arn_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckRoleARN(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessRoleARNAssociationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessRoleARNAssociationConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDRTAccessRoleARNAssociationExists(ctx, resourceName, &drtaccessrolearnassociation), + ), + }, + }, + }) +} + +func TestAccShieldDRTAccessRoleARNAssociation_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var drtaccessrolearnassociation shield.DescribeDRTAccessOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_shield_drt_access_role_arn_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheckRoleARN(ctx, t) + }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDRTAccessRoleARNAssociationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDRTAccessRoleARNAssociationConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDRTAccessRoleARNAssociationExists(ctx, resourceName, &drtaccessrolearnassociation), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfshield.ResourceDRTAccessRoleARNAssociation, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckDRTAccessRoleARNAssociationDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_shield_drt_access_role_arn_association" { + continue + } + + input := &shield.DescribeDRTAccessInput{} + resp, err := conn.DescribeDRTAccessWithContext(ctx, input) + + if errs.IsA[*shield.ResourceNotFoundException](err) { + return nil + } + + if resp != nil && (resp.RoleARN == nil || *resp.RoleARN == "") { + return nil + } + + return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessRoleARNAssociation, rs.Primary.ID, errors.New("not destroyed")) + } + return nil + } +} + +func testAccCheckDRTAccessRoleARNAssociationExists(ctx context.Context, name string, drtaccessrolearnassociation *shield.DescribeDRTAccessOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not set")) + } + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + resp, err := conn.DescribeDRTAccessWithContext(ctx, &shield.DescribeDRTAccessInput{}) + if err != nil { + return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessRoleARNAssociation, "testing", err) + } + + *drtaccessrolearnassociation = *resp + return nil + } +} + +func testAccPreCheckRoleARN(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) + + input := &shield.DescribeDRTAccessInput{} + _, err := conn.DescribeDRTAccessWithContext(ctx, input) + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccDRTAccessRoleARNAssociationConfig_basic(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Sid" : "", + "Effect" : "Allow", + "Principal" : { + "Service" : "drt.shield.amazonaws.com" + }, + "Action" : "sts:AssumeRole" + }, + ] + }) +} + +resource "aws_shield_protection_group" "test" { + protection_group_id = %[1]q + aggregation = "MAX" + pattern = "ALL" +} + +resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" +} + +resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn +} +`, rName) +} diff --git a/internal/service/shield/exports_test.go b/internal/service/shield/exports_test.go new file mode 100644 index 00000000000..4b16a87d49d --- /dev/null +++ b/internal/service/shield/exports_test.go @@ -0,0 +1,10 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package shield + +// Exports for use in tests only. +var ( + ResourceDRTAccessRoleARNAssociation = newResourceDRTAccessRoleARNAssociation + ResourceDRTAccessLogBucketAssociation = newResourceDRTAccessLogBucketAssociation +) diff --git a/internal/service/shield/service_package_gen.go b/internal/service/shield/service_package_gen.go index 91d134d2748..a48c151816f 100644 --- a/internal/service/shield/service_package_gen.go +++ b/internal/service/shield/service_package_gen.go @@ -17,7 +17,16 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourceDRTAccessLogBucketAssociation, + Name: "DRT Access Log Bucket Association", + }, + { + Factory: newResourceDRTAccessRoleArnAssociation, + Name: "DRT Access Role Arn Association", + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { diff --git a/website/docs/r/shield_drt_access_log_bucket_association.html.markdown b/website/docs/r/shield_drt_access_log_bucket_association.html.markdown new file mode 100644 index 00000000000..18fbcf97747 --- /dev/null +++ b/website/docs/r/shield_drt_access_log_bucket_association.html.markdown @@ -0,0 +1,35 @@ +--- +subcategory: "Shield" +layout: "aws" +page_title: "AWS: aws_shield_drt_access_log_bucket_association" +description: |- + Terraform resource for managing an AWS Shield DRT Access Log Bucket Association. +--- +# Resource: aws_shield_drt_access_log_bucket_association + +Terraform resource for managing an AWS Shield DRT Access Log Bucket Association. Up to 10 log buckets can be associated for DRT Access sharing with the Shield Response Team (SRT). + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = "arn:aws:iam:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:${var.shield_drt_access_role_name}" +} + +resource "aws_shield_drt_access_log_bucket_association" "test" { + log_bucket = var.shield_drt_access_log_bucket + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id +} +``` + +## Argument Reference + +The following arguments are required: + +* `log_bucket` - (Required) The Amazon S3 bucket that contains the logs that you want to share. +* `role_arn_association_id` - (Required) The ID of the Role Arn association used for allowing Shield DRT Access. + +## Attribute Reference +This resource exports no additional attributes. diff --git a/website/docs/r/shield_drt_access_role_arn_association.html.markdown b/website/docs/r/shield_drt_access_role_arn_association.html.markdown new file mode 100644 index 00000000000..a7a8d6c1146 --- /dev/null +++ b/website/docs/r/shield_drt_access_role_arn_association.html.markdown @@ -0,0 +1,51 @@ +--- +subcategory: "Shield" +layout: "aws" +page_title: "AWS: aws_shield_drt_access_role_arn_association" +description: |- + Terraform resource for managing an AWS Shield DRT Access Role Arn Association. +--- +# Resource: aws_shield_drt_access_role_arn_association + +Authorizes the Shield Response Team (SRT) using the specified role, to access your AWS account to assist with DDoS attack mitigation during potential attacks. For more information see [Configure AWS SRT Support](https://docs.aws.amazon.com/waf/latest/developerguide/authorize-srt.html) + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_iam_role" "test" { + name = var.aws_shield_drt_access_role_arn + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Sid" : "", + "Effect" : "Allow", + "Principal" : { + "Service" : "drt.shield.amazonaws.com" + }, + "Action" : "sts:AssumeRole" + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" +} + +resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn +} +``` + +## Argument Reference + +The following arguments are required: + +* `role_arn` - (Required) The Amazon Resource Name (ARN) of the role the SRT will use to access your AWS account. Prior to making the AssociateDRTRole request, you must attach the `AWSShieldDRTAccessPolicy` managed policy to this role. + +## Attribute Reference +This resource exports no additional attributes. From a46c9a777d619bd3c3b7c39a8431132e146fa6a4 Mon Sep 17 00:00:00 2001 From: Shawn Chasse Date: Tue, 5 Sep 2023 14:49:35 -0400 Subject: [PATCH 02/15] Revert bad commit --- .../drt_access_log_bucket_association.go | 531 ++++++++++-------- .../service/shield/service_package_gen.go | 8 +- 2 files changed, 313 insertions(+), 226 deletions(-) diff --git a/internal/service/shield/drt_access_log_bucket_association.go b/internal/service/shield/drt_access_log_bucket_association.go index 8af1b75f8a6..5fa441151d2 100644 --- a/internal/service/shield/drt_access_log_bucket_association.go +++ b/internal/service/shield/drt_access_log_bucket_association.go @@ -1,292 +1,379 @@ -package shield_test +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package shield import ( "context" "errors" - "fmt" - - //"regexp" - "testing" + "time" - "github.com/aws/aws-sdk-go-v2/service/shield/types" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go/service/shield" - sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/hashicorp/terraform-provider-aws/internal/acctest" - "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="DRT Access Log Bucket Association") +func newResourceDRTAccessLogBucketAssociation(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceDRTAccessLogBucketAssociation{} + + r.SetDefaultCreateTimeout(30 * time.Minute) + r.SetDefaultUpdateTimeout(30 * time.Minute) + r.SetDefaultDeleteTimeout(30 * time.Minute) + + return r, nil +} - tfshield "github.com/hashicorp/terraform-provider-aws/internal/service/shield" +const ( + ResNameDRTAccessLogBucketAssociation = "DRT Access Log Bucket Association" ) -func TestAccShieldDRTAccessLogBucketAssociation_basic(t *testing.T) { - ctx := acctest.Context(t) +type resourceDRTAccessLogBucketAssociation struct { + framework.ResourceWithConfigure + framework.WithTimeouts +} - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_shield_drt_access_log_bucket_association.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckLogBucket(ctx, t) - }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), - Steps: []resource.TestStep{ - { - Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), - Check: testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), +func (r *resourceDRTAccessLogBucketAssociation) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_shield_drt_access_log_bucket_association" +} + +func (r *resourceDRTAccessLogBucketAssociation) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ // required by hashicorps terraform plugin testing framework + DeprecationMessage: "id is only for framework compatibility and not used by the provider", + MarkdownDescription: "The ID of the directory.", + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "log_bucket": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + // Validate string value length must be at least 3 characters and max 63. + stringvalidator.LengthBetween(3, 63), + }, }, + "role_arn_association_id": schema.StringAttribute{ + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "timeouts": timeouts.Block(ctx, timeouts.Opts{ + Create: true, + Delete: true, + Read: true, + }), }, - }) + } } -func TestAccShieldDRTAccessLogBucketAssociation_multibucket(t *testing.T) { - ctx := acctest.Context(t) +func (r *resourceDRTAccessLogBucketAssociation) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().ShieldConn(ctx) - if testing.Short() { - t.Skip("skipping long-running test in short mode") + var plan resourceDRTAccessLogBucketAssociationData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return } - var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var buckets = []string{} - for i := 0; i < 2; i++ { - buckets = append(buckets, sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)) - } - resourceName1 := "aws_shield_drt_access_log_bucket_association.test1" - resourceName2 := "aws_shield_drt_access_log_bucket_association.test2" - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckLogBucket(ctx, t) - }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), - Steps: []resource.TestStep{ - { - Config: testAccDRTAccessLogBucketAssociationConfig_multibucket(rName, buckets, t), - Check: resource.ComposeTestCheckFunc( - testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName1, &drtaccesslogbucketassociation, t), - testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName2, &drtaccesslogbucketassociation, t), - ), - }, - }, - }) -} + in := &shield.AssociateDRTLogBucketInput{ + LogBucket: aws.String(plan.LogBucket.ValueString()), + } + out, err := conn.AssociateDRTLogBucketWithContext(ctx, in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionCreating, ResNameDRTAccessLogBucketAssociation, plan.LogBucket.String(), err), + err.Error(), + ) + return + } + if out == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionCreating, ResNameDRTAccessLogBucketAssociation, plan.LogBucket.String(), nil), + errors.New("empty output").Error(), + ) + return + } -func TestAccShieldDRTAccessLogBucketAssociation_disappears(t *testing.T) { - ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") + createTimeout := r.CreateTimeout(ctx, plan.Timeouts) + _, err = waitDRTAccessLogBucketAssociationCreated(ctx, conn, plan.LogBucket.ValueString(), createTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionWaitingForCreation, ResNameDRTAccessLogBucketAssociation, plan.LogBucket.String(), err), + err.Error(), + ) + return } - var drtaccesslogbucketassociation shield.DescribeDRTAccessOutput - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_shield_drt_access_log_bucket_association.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - testAccPreCheckLogBucket(ctx, t) - }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), - Steps: []resource.TestStep{ - { - Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), - Check: resource.ComposeTestCheckFunc( - testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), - acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfshield.ResourceDRTAccessLogBucketAssociation, resourceName), - ), - ExpectNonEmptyPlan: true, - }, - }, - }) + plan.ID = types.StringValue(plan.LogBucket.ValueString()) + + resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) } -func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context, t *testing.T) resource.TestCheckFunc { - return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) +func (r *resourceDRTAccessLogBucketAssociation) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().ShieldConn(ctx) - for _, rs := range s.RootModule().Resources { - if rs.Type != "aws_shield_drt_access_log_bucket_association" { - continue - } + var state resourceDRTAccessLogBucketAssociationData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + in := &shield.DescribeDRTAccessInput{} - input := &shield.DescribeDRTAccessInput{} - resp, err := conn.DescribeDRTAccessWithContext(ctx, input) + out, err := conn.DescribeDRTAccessWithContext(ctx, in) + if tfresource.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } - if errs.IsA[*types.ResourceNotFoundException](err) { - return nil - } - if err != nil { - return nil - } - if resp != nil { - if resp.LogBucketList != nil && len(resp.LogBucketList) > 0 { - for _, bucket := range resp.LogBucketList { + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionSetting, ResNameDRTAccessLogBucketAssociation, state.LogBucket.String(), err), + err.Error(), + ) + return + } + var associatedLogBucket *string + if out != nil { + associatedLogBucket = getAssociatedLogBucket(state.LogBucket.ValueString(), out.LogBucketList) + if len(out.LogBucketList) > 0 && associatedLogBucket == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionSetting, ResNameDRTAccessLogBucketAssociation, state.LogBucket.String(), nil), + errors.New("Log Bucket not in list").Error(), + ) + } + } - if *bucket == rs.Primary.Attributes["log_bucket"] { - return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, errors.New("bucket association not destroyed")) - } - } + if state.ID.IsNull() || state.ID.IsUnknown() { + // Setting ID of state - required by hashicorps terraform plugin testing framework for Import. See issue https://github.com/hashicorp/terraform-plugin-testing/issues/84 + state.ID = types.StringValue(state.LogBucket.ValueString()) + } + state.LogBucket = flex.StringToFramework(ctx, associatedLogBucket) - } - return nil - } + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} - return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, errors.New("not destroyed")) +func getAssociatedLogBucket(bucket string, bucketList []*string) *string { + for _, bkt := range bucketList { + if aws.ToString(bkt) == bucket { + return bkt } - - return nil } + return nil } -func testAccCheckDRTAccessLogBucketAssociationExists(ctx context.Context, name string, drtaccesslogbucketassociation *shield.DescribeDRTAccessOutput, t *testing.T) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] +func (r *resourceDRTAccessLogBucketAssociation) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().ShieldConn(ctx) - if !ok { - return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not found")) - } + var plan, state resourceDRTAccessLogBucketAssociationData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } - if rs.Primary.ID == "" { - return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, name, errors.New("not set")) + if !plan.LogBucket.Equal(state.LogBucket) { + in := &shield.AssociateDRTLogBucketInput{ + LogBucket: aws.String(plan.LogBucket.ValueString()), } - - conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) - resp, err := conn.DescribeDRTAccessWithContext(ctx, &shield.DescribeDRTAccessInput{}) + out, err := conn.AssociateDRTLogBucketWithContext(ctx, in) if err != nil { - return create.Error(names.Shield, create.ErrActionCheckingExistence, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, err) + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionUpdating, ResNameDRTAccessLogBucketAssociation, plan.LogBucket.String(), err), + err.Error(), + ) + return } + if out == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionUpdating, ResNameDRTAccessLogBucketAssociation, plan.LogBucket.String(), nil), + errors.New("empty output").Error(), + ) + return + } + } - *drtaccesslogbucketassociation = *resp - - return nil + updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) + _, err := waitDRTAccessLogBucketAssociationUpdated(ctx, conn, plan.LogBucket.ValueString(), updateTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionWaitingForUpdate, ResNameDRTAccessLogBucketAssociation, plan.LogBucket.String(), err), + err.Error(), + ) + return } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) } -func testAccPreCheckLogBucket(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) +func (r *resourceDRTAccessLogBucketAssociation) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().ShieldConn(ctx) - input := &shield.DescribeDRTAccessInput{} - _, err := conn.DescribeDRTAccessWithContext(ctx, input) + var state resourceDRTAccessLogBucketAssociationData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.LogBucket.ValueString() == "" { + return + } - if acctest.PreCheckSkipError(err) { - t.Skipf("skipping acceptance testing: %s", err) + in := &shield.DisassociateDRTLogBucketInput{ + LogBucket: aws.String(state.LogBucket.ValueString()), } + + _, err := conn.DisassociateDRTLogBucketWithContext(ctx, in) if err != nil { - t.Fatalf("unexpected PreCheck error: %s", err) + var nfe *shield.ResourceNotFoundException + if errors.As(err, &nfe) { + return + } + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionDeleting, ResNameDRTAccessLogBucketAssociation, state.LogBucket.String(), err), + err.Error(), + ) + return + } + deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) + _, err = waitDRTAccessLogBucketAssociationDeleted(ctx, conn, state.LogBucket.ValueString(), deleteTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.Shield, create.ErrActionWaitingForDeletion, ResNameDRTAccessLogBucketAssociation, state.LogBucket.String(), err), + err.Error(), + ) + return } } -func testAccDRTAccessLogBucketAssociationConfig_basic(rName string, bucket string, t *testing.T) string { +const ( + statusChangePending = "Pending" + statusDeleting = "Deleting" + statusNormal = "Normal" + statusUpdated = "Updated" +) - return fmt.Sprintf(` - resource "aws_s3_bucket" "test" { - bucket = %[2]q +func waitDRTAccessLogBucketAssociationCreated(ctx context.Context, conn *shield.Shield, bucket string, timeout time.Duration) (*shield.DescribeDRTAccessOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{}, + Target: []string{statusNormal}, + Refresh: statusDRTAccessLogBucketAssociation(ctx, conn, bucket), + Timeout: timeout, + NotFoundChecks: 2, + ContinuousTargetOccurence: 2, } - resource "aws_iam_role" "test" { - name = %[1]q - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - "Sid": "", - "Effect": "Allow", - "Principal": { - "Service": "drt.shield.amazonaws.com" - }, - "Action": "sts:AssumeRole" - }, - ] - }) + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*shield.DescribeDRTAccessOutput); ok { + return out, err } - - resource "aws_iam_role_policy_attachment" "test" { - role = aws_iam_role.test.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" + + return nil, err +} + +func waitDRTAccessLogBucketAssociationUpdated(ctx context.Context, conn *shield.Shield, bucket string, timeout time.Duration) (*shield.DescribeDRTAccessOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{statusChangePending}, + Target: []string{statusUpdated}, + Refresh: statusDRTAccessLogBucketAssociation(ctx, conn, bucket), + Timeout: timeout, + NotFoundChecks: 2, + ContinuousTargetOccurence: 2, } - resource "aws_shield_protection_group" "test" { - protection_group_id = %[1]q - aggregation = "MAX" - pattern = "ALL" + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*shield.DescribeDRTAccessOutput); ok { + return out, err } - - resource "aws_shield_drt_access_role_arn_association" "test" { - role_arn = aws_iam_role.test.arn + + return nil, err +} + +func waitDRTAccessLogBucketAssociationDeleted(ctx context.Context, conn *shield.Shield, bucket string, timeout time.Duration) (*shield.DescribeDRTAccessOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{statusDeleting, statusNormal}, + Target: []string{}, + Refresh: statusDRTAccessLogBucketAssociation(ctx, conn, bucket), + Timeout: timeout, } - resource "aws_shield_drt_access_log_bucket_association" "test" { - log_bucket = aws_s3_bucket.test.id - role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*shield.DescribeDRTAccessOutput); ok { + return out, err } -`, rName, bucket) + + return nil, err } -func testAccDRTAccessLogBucketAssociationConfig_multibucket(rName string, buckets []string, t *testing.T) string { +func statusDRTAccessLogBucketAssociation(ctx context.Context, conn *shield.Shield, bucket string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := describeDRTAccessLogBucketAssociation(ctx, conn, bucket) + if tfresource.NotFound(err) { + return nil, "", nil + } - return fmt.Sprintf(` - resource "aws_s3_bucket" "test1" { - bucket = %[2]q - } - resource "aws_s3_bucket" "test2" { - bucket = %[3]q - } + if err != nil { + return nil, "", err + } + if out == nil || out.LogBucketList == nil || len(out.LogBucketList) == 0 { + return nil, "", nil + } - resource "aws_iam_role" "test" { - name = %[1]q - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - "Sid": "", - "Effect": "Allow", - "Principal": { - "Service": "drt.shield.amazonaws.com" - }, - "Action": "sts:AssumeRole" - }, - ] - }) - } - - resource "aws_iam_role_policy_attachment" "test" { - role = aws_iam_role.test.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" - } + if out != nil && len(out.LogBucketList) > 0 { + for _, bkt := range out.LogBucketList { + if aws.ToString(bkt) == bucket { + return out, statusNormal, nil + } + } + return nil, "", nil + } - resource "aws_shield_protection_group" "test" { - protection_group_id = %[1]q - aggregation = "MAX" - pattern = "ALL" + return out, statusNormal, nil } - - resource "aws_shield_drt_access_role_arn_association" "test" { - role_arn = aws_iam_role.test.arn +} + +func describeDRTAccessLogBucketAssociation(ctx context.Context, conn *shield.Shield, bucketName string) (*shield.DescribeDRTAccessOutput, error) { + in := &shield.DescribeDRTAccessInput{} + + out, err := conn.DescribeDRTAccessWithContext(ctx, in) + if err != nil { + var nfe *shield.ResourceNotFoundException + if errors.As(err, &nfe) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } } - resource "aws_shield_drt_access_log_bucket_association" "test1" { - log_bucket = aws_s3_bucket.test1.id - role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + if out == nil || out.LogBucketList == nil || len(out.LogBucketList) == 0 { + return nil, tfresource.NewEmptyResultError(in) } - resource "aws_shield_drt_access_log_bucket_association" "test2" { - log_bucket = aws_s3_bucket.test2.id - role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id - depends_on = [ - aws_shield_drt_access_log_bucket_association.test1 - ] + + for _, bucket := range out.LogBucketList { + if aws.ToString(bucket) == bucketName { + return out, nil + } } -`, rName, buckets[0], buckets[1]) + return nil, err +} + +type resourceDRTAccessLogBucketAssociationData struct { + ID types.String `tfsdk:"id"` + RoleArnAssociationID types.String `tfsdk:"role_arn_association_id"` + LogBucket types.String `tfsdk:"log_bucket"` + Timeouts timeouts.Value `tfsdk:"timeouts"` } diff --git a/internal/service/shield/service_package_gen.go b/internal/service/shield/service_package_gen.go index a48c151816f..8d9b5a41054 100644 --- a/internal/service/shield/service_package_gen.go +++ b/internal/service/shield/service_package_gen.go @@ -18,15 +18,15 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { return []*types.ServicePackageFrameworkResource{ - { + { Factory: newResourceDRTAccessLogBucketAssociation, Name: "DRT Access Log Bucket Association", }, { - Factory: newResourceDRTAccessRoleArnAssociation, - Name: "DRT Access Role Arn Association", + Factory: newResourceDRTAccessRoleARNAssociation, + Name: "DRT Access Role ARN Association", }, - } + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { From b7bfa022ab8bd51809574469b9e0f3d571038642 Mon Sep 17 00:00:00 2001 From: Shawn Chasse Date: Wed, 6 Sep 2023 09:34:08 -0400 Subject: [PATCH 03/15] Revert bad commit --- internal/service/shield/drt_access_role_arn_association_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/shield/drt_access_role_arn_association_test.go b/internal/service/shield/drt_access_role_arn_association_test.go index 0c995501923..1eaaa68b31a 100644 --- a/internal/service/shield/drt_access_role_arn_association_test.go +++ b/internal/service/shield/drt_access_role_arn_association_test.go @@ -96,7 +96,7 @@ func testAccCheckDRTAccessRoleARNAssociationDestroy(ctx context.Context) resourc return nil } - if resp != nil && (resp.RoleARN == nil || *resp.RoleARN == "") { + if resp != nil && (resp.RoleArn == nil || *resp.RoleArn == "") { return nil } From 599e68004a4109f4ac2e4b33a8a7a21a1f548725 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 10:23:22 -0400 Subject: [PATCH 04/15] Add CHANGELOG entries. --- .changelog/33328.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/33328.txt diff --git a/.changelog/33328.txt b/.changelog/33328.txt new file mode 100644 index 00000000000..edb5974d7bf --- /dev/null +++ b/.changelog/33328.txt @@ -0,0 +1,7 @@ +```release-note:new-resource +aws_shield_drt_access_log_bucket_association +``` + +```release-note:new-resource +aws_shield_drt_access_role_arn_association +``` From eb092906ced8a446fd9604670dc50aaf1b2edf1b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 10:25:23 -0400 Subject: [PATCH 05/15] Add copywrite headers. --- .../service/shield/drt_access_log_bucket_association_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index 8af1b75f8a6..d4a09c10817 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package shield_test import ( From 0fdcb7f28354df5632974178099ad898934135b9 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 10:43:30 -0400 Subject: [PATCH 06/15] Fix compilation errors. --- .../service/shield/drt_access_log_bucket_association.go | 8 ++++---- .../shield/drt_access_log_bucket_association_test.go | 5 +---- .../service/shield/drt_access_role_arn_association.go | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/internal/service/shield/drt_access_log_bucket_association.go b/internal/service/shield/drt_access_log_bucket_association.go index 5fa441151d2..faa84be8648 100644 --- a/internal/service/shield/drt_access_log_bucket_association.go +++ b/internal/service/shield/drt_access_log_bucket_association.go @@ -8,7 +8,7 @@ import ( "errors" "time" - "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/shield" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -169,7 +169,7 @@ func (r *resourceDRTAccessLogBucketAssociation) Read(ctx context.Context, req re func getAssociatedLogBucket(bucket string, bucketList []*string) *string { for _, bkt := range bucketList { - if aws.ToString(bkt) == bucket { + if aws.StringValue(bkt) == bucket { return bkt } } @@ -334,7 +334,7 @@ func statusDRTAccessLogBucketAssociation(ctx context.Context, conn *shield.Shiel if out != nil && len(out.LogBucketList) > 0 { for _, bkt := range out.LogBucketList { - if aws.ToString(bkt) == bucket { + if aws.StringValue(bkt) == bucket { return out, statusNormal, nil } } @@ -364,7 +364,7 @@ func describeDRTAccessLogBucketAssociation(ctx context.Context, conn *shield.Shi } for _, bucket := range out.LogBucketList { - if aws.ToString(bucket) == bucketName { + if aws.StringValue(bucket) == bucketName { return out, nil } } diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index d4a09c10817..fdbb5d93473 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -7,11 +7,8 @@ import ( "context" "errors" "fmt" - - //"regexp" "testing" - "github.com/aws/aws-sdk-go-v2/service/shield/types" "github.com/aws/aws-sdk-go/service/shield" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -128,7 +125,7 @@ func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context, t *te input := &shield.DescribeDRTAccessInput{} resp, err := conn.DescribeDRTAccessWithContext(ctx, input) - if errs.IsA[*types.ResourceNotFoundException](err) { + if errs.IsA[*shield.ResourceNotFoundException](err) { return nil } if err != nil { diff --git a/internal/service/shield/drt_access_role_arn_association.go b/internal/service/shield/drt_access_role_arn_association.go index 0c1da5254dc..cf5fa01b3f4 100644 --- a/internal/service/shield/drt_access_role_arn_association.go +++ b/internal/service/shield/drt_access_role_arn_association.go @@ -9,7 +9,7 @@ import ( "regexp" "time" - "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/shield" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -323,7 +323,7 @@ func statusDRTAccessRoleARNAssociationDeleted(ctx context.Context, conn *shield. return nil, "", err } - if out.RoleArn != nil && aws.ToString(out.RoleArn) == roleARN { + if out.RoleArn != nil && aws.StringValue(out.RoleArn) == roleARN { return out, statusDeleting, nil } @@ -345,7 +345,7 @@ func describeDRTAccessRoleARNAssociation(ctx context.Context, conn *shield.Shiel } } - if out == nil || out.RoleArn == nil || aws.ToString(out.RoleArn) != roleARN { + if out == nil || out.RoleArn == nil || aws.StringValue(out.RoleArn) != roleARN { return nil, tfresource.NewEmptyResultError(in) } From 820d189040c29581e02df01ce9bce419e91cdb51 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 10:48:55 -0400 Subject: [PATCH 07/15] Fix semgrep 'ci.calling-regexp.MustCompile-directly'. --- internal/service/shield/drt_access_role_arn_association.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/shield/drt_access_role_arn_association.go b/internal/service/shield/drt_access_role_arn_association.go index cf5fa01b3f4..8b7aa76d859 100644 --- a/internal/service/shield/drt_access_role_arn_association.go +++ b/internal/service/shield/drt_access_role_arn_association.go @@ -6,9 +6,9 @@ package shield import ( "context" "errors" - "regexp" "time" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/shield" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" @@ -68,7 +68,7 @@ func (r *resourceDRTAccessRoleARNAssociation) Schema(ctx context.Context, req re Validators: []validator.String{ stringvalidator.LengthBetween(1, 2048), stringvalidator.RegexMatches( - regexp.MustCompile(`^arn:?[a-zA-Z\-]+:iam::\d{12}:role/?[a-zA-Z_0-9+=,.@\-_/]+`), + regexache.MustCompile(`^arn:?[a-zA-Z\-]+:iam::\d{12}:role/?[a-zA-Z_0-9+=,.@\-_/]+`), "must match arn pattern", ), }, From 3e3f85301aaa7f9687c968935da17d95ba9c391e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 10:53:07 -0400 Subject: [PATCH 08/15] Fix terrafmt errors. --- .../drt_access_log_bucket_association_test.go | 168 +++++++++--------- 1 file changed, 82 insertions(+), 86 deletions(-) diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index fdbb5d93473..623733a6281 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -190,103 +190,99 @@ func testAccPreCheckLogBucket(ctx context.Context, t *testing.T) { } func testAccDRTAccessLogBucketAssociationConfig_basic(rName string, bucket string, t *testing.T) string { - return fmt.Sprintf(` - resource "aws_s3_bucket" "test" { - bucket = %[2]q - } +resource "aws_s3_bucket" "test" { + bucket = %[2]q +} - resource "aws_iam_role" "test" { - name = %[1]q - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - "Sid": "", - "Effect": "Allow", - "Principal": { - "Service": "drt.shield.amazonaws.com" - }, - "Action": "sts:AssumeRole" - }, - ] - }) - } - - resource "aws_iam_role_policy_attachment" "test" { - role = aws_iam_role.test.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" - } +resource "aws_iam_role" "test" { + name = %[1]q + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "drt.shield.amazonaws.com" + }, + "Action": "sts:AssumeRole" + }] + }) +} - resource "aws_shield_protection_group" "test" { - protection_group_id = %[1]q - aggregation = "MAX" - pattern = "ALL" - } - - resource "aws_shield_drt_access_role_arn_association" "test" { - role_arn = aws_iam_role.test.arn - } +resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" +} - resource "aws_shield_drt_access_log_bucket_association" "test" { - log_bucket = aws_s3_bucket.test.id - role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id - } +resource "aws_shield_protection_group" "test" { + protection_group_id = %[1]q + aggregation = "MAX" + pattern = "ALL" +} + +resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn +} + +resource "aws_shield_drt_access_log_bucket_association" "test" { + log_bucket = aws_s3_bucket.test.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id +} `, rName, bucket) } func testAccDRTAccessLogBucketAssociationConfig_multibucket(rName string, buckets []string, t *testing.T) string { - return fmt.Sprintf(` - resource "aws_s3_bucket" "test1" { - bucket = %[2]q - } - resource "aws_s3_bucket" "test2" { - bucket = %[3]q - } +resource "aws_s3_bucket" "test1" { + bucket = %[2]q +} - resource "aws_iam_role" "test" { - name = %[1]q - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - "Sid": "", - "Effect": "Allow", - "Principal": { - "Service": "drt.shield.amazonaws.com" - }, - "Action": "sts:AssumeRole" - }, - ] - }) - } - - resource "aws_iam_role_policy_attachment" "test" { - role = aws_iam_role.test.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" - } +resource "aws_s3_bucket" "test2" { + bucket = %[3]q +} - resource "aws_shield_protection_group" "test" { - protection_group_id = %[1]q - aggregation = "MAX" - pattern = "ALL" - } - - resource "aws_shield_drt_access_role_arn_association" "test" { - role_arn = aws_iam_role.test.arn - } +resource "aws_iam_role" "test" { + name = %[1]q + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "drt.shield.amazonaws.com" + }, + "Action": "sts:AssumeRole" + }] + }) +} - resource "aws_shield_drt_access_log_bucket_association" "test1" { - log_bucket = aws_s3_bucket.test1.id - role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id - } - resource "aws_shield_drt_access_log_bucket_association" "test2" { - log_bucket = aws_s3_bucket.test2.id - role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id - depends_on = [ - aws_shield_drt_access_log_bucket_association.test1 - ] - } +resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" +} + +resource "aws_shield_protection_group" "test" { + protection_group_id = %[1]q + aggregation = "MAX" + pattern = "ALL" +} + +resource "aws_shield_drt_access_role_arn_association" "test" { + role_arn = aws_iam_role.test.arn +} + +resource "aws_shield_drt_access_log_bucket_association" "test1" { + log_bucket = aws_s3_bucket.test1.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id +} +resource "aws_shield_drt_access_log_bucket_association" "test2" { + log_bucket = aws_s3_bucket.test2.id + role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id + + depends_on = [aws_shield_drt_access_log_bucket_association.test1] +} `, rName, buckets[0], buckets[1]) } From 59236168c2cacb454a6616c9ed92206498e0ef37 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 10:57:22 -0400 Subject: [PATCH 09/15] Fix terrafmt errors. --- .../drt_access_log_bucket_association_test.go | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index 623733a6281..be47370a9bf 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -201,12 +201,12 @@ resource "aws_iam_role" "test" { assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ - "Sid": "", - "Effect": "Allow", - "Principal": { - "Service": "drt.shield.amazonaws.com" + "Sid" : "", + "Effect" : "Allow", + "Principal" : { + "Service" : "drt.shield.amazonaws.com" }, - "Action": "sts:AssumeRole" + "Action" : "sts:AssumeRole" }] }) } @@ -249,12 +249,12 @@ resource "aws_iam_role" "test" { assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ - "Sid": "", - "Effect": "Allow", - "Principal": { - "Service": "drt.shield.amazonaws.com" + "Sid" : "", + "Effect" : "Allow", + "Principal" : { + "Service" : "drt.shield.amazonaws.com" }, - "Action": "sts:AssumeRole" + "Action" : "sts:AssumeRole" }] }) } From 1ce4749e0e0bc06965eb3e944acd94b75e1119bb Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 11:05:49 -0400 Subject: [PATCH 10/15] Fix importlint errors. --- .../service/shield/drt_access_log_bucket_association_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index be47370a9bf..0e9cc4e1b55 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -17,9 +17,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/errs" - "github.com/hashicorp/terraform-provider-aws/names" - tfshield "github.com/hashicorp/terraform-provider-aws/internal/service/shield" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccShieldDRTAccessLogBucketAssociation_basic(t *testing.T) { From e59a772965f35bdeb0443a6ad3d1f45026a941b8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 11:07:13 -0400 Subject: [PATCH 11/15] Fix markdown-lint 'MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below]'. --- .../r/shield_drt_access_log_bucket_association.html.markdown | 1 + .../docs/r/shield_drt_access_role_arn_association.html.markdown | 1 + 2 files changed, 2 insertions(+) diff --git a/website/docs/r/shield_drt_access_log_bucket_association.html.markdown b/website/docs/r/shield_drt_access_log_bucket_association.html.markdown index 18fbcf97747..bc391f86ba3 100644 --- a/website/docs/r/shield_drt_access_log_bucket_association.html.markdown +++ b/website/docs/r/shield_drt_access_log_bucket_association.html.markdown @@ -32,4 +32,5 @@ The following arguments are required: * `role_arn_association_id` - (Required) The ID of the Role Arn association used for allowing Shield DRT Access. ## Attribute Reference + This resource exports no additional attributes. diff --git a/website/docs/r/shield_drt_access_role_arn_association.html.markdown b/website/docs/r/shield_drt_access_role_arn_association.html.markdown index a7a8d6c1146..efdc1437e7d 100644 --- a/website/docs/r/shield_drt_access_role_arn_association.html.markdown +++ b/website/docs/r/shield_drt_access_role_arn_association.html.markdown @@ -48,4 +48,5 @@ The following arguments are required: * `role_arn` - (Required) The Amazon Resource Name (ARN) of the role the SRT will use to access your AWS account. Prior to making the AssociateDRTRole request, you must attach the `AWSShieldDRTAccessPolicy` managed policy to this role. ## Attribute Reference + This resource exports no additional attributes. From 5df93ee91873512ebd8241b87bb45a3e37a6c6ef Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 11:09:46 -0400 Subject: [PATCH 12/15] Fix providerlint 'AWSAT005: avoid hardcoded ARN AWS partitions, use aws_partition data source'. --- .../shield/drt_access_log_bucket_association_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index 0e9cc4e1b55..2def2bc2e50 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -190,6 +190,8 @@ func testAccPreCheckLogBucket(ctx context.Context, t *testing.T) { func testAccDRTAccessLogBucketAssociationConfig_basic(rName string, bucket string, t *testing.T) string { return fmt.Sprintf(` +data "aws_partition" "current" {} + resource "aws_s3_bucket" "test" { bucket = %[2]q } @@ -212,7 +214,7 @@ resource "aws_iam_role" "test" { resource "aws_iam_role_policy_attachment" "test" { role = aws_iam_role.test.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" + policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" } resource "aws_shield_protection_group" "test" { @@ -234,6 +236,8 @@ resource "aws_shield_drt_access_log_bucket_association" "test" { func testAccDRTAccessLogBucketAssociationConfig_multibucket(rName string, buckets []string, t *testing.T) string { return fmt.Sprintf(` +data "aws_partition" "current" {} + resource "aws_s3_bucket" "test1" { bucket = %[2]q } @@ -260,7 +264,7 @@ resource "aws_iam_role" "test" { resource "aws_iam_role_policy_attachment" "test" { role = aws_iam_role.test.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" + policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy" } resource "aws_shield_protection_group" "test" { From e357ffafb4961fffae0a3feb6dae3fb3347eb68f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 11:16:03 -0400 Subject: [PATCH 13/15] Fix terrafmt errors. --- .../service/shield/drt_access_log_bucket_association_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index 2def2bc2e50..6b01a5d5852 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -243,7 +243,7 @@ resource "aws_s3_bucket" "test1" { } resource "aws_s3_bucket" "test2" { - bucket = %[3]q + bucket = %[3]q } resource "aws_iam_role" "test" { @@ -281,6 +281,7 @@ resource "aws_shield_drt_access_log_bucket_association" "test1" { log_bucket = aws_s3_bucket.test1.id role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id } + resource "aws_shield_drt_access_log_bucket_association" "test2" { log_bucket = aws_s3_bucket.test2.id role_arn_association_id = aws_shield_drt_access_role_arn_association.test.id From 320000c2789a0396f4da29ecbc27abb07c5c3544 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 11:51:36 -0400 Subject: [PATCH 14/15] Fix golangci-lint errors. --- .../drt_access_log_bucket_association_test.go | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/internal/service/shield/drt_access_log_bucket_association_test.go b/internal/service/shield/drt_access_log_bucket_association_test.go index 6b01a5d5852..e824e9c73a1 100644 --- a/internal/service/shield/drt_access_log_bucket_association_test.go +++ b/internal/service/shield/drt_access_log_bucket_association_test.go @@ -38,11 +38,11 @@ func TestAccShieldDRTAccessLogBucketAssociation_basic(t *testing.T) { testAccPreCheckLogBucket(ctx, t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), - Check: testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), + Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName), + Check: testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation), }, }, }) @@ -69,13 +69,13 @@ func TestAccShieldDRTAccessLogBucketAssociation_multibucket(t *testing.T) { testAccPreCheckLogBucket(ctx, t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccDRTAccessLogBucketAssociationConfig_multibucket(rName, buckets, t), + Config: testAccDRTAccessLogBucketAssociationConfig_multibucket(rName, buckets), Check: resource.ComposeTestCheckFunc( - testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName1, &drtaccesslogbucketassociation, t), - testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName2, &drtaccesslogbucketassociation, t), + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName1, &drtaccesslogbucketassociation), + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName2, &drtaccesslogbucketassociation), ), }, }, @@ -98,12 +98,12 @@ func TestAccShieldDRTAccessLogBucketAssociation_disappears(t *testing.T) { testAccPreCheckLogBucket(ctx, t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx, t), + CheckDestroy: testAccCheckDRTAccessLogBucketAssociationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName, t), + Config: testAccDRTAccessLogBucketAssociationConfig_basic(rName, bucketName), Check: resource.ComposeTestCheckFunc( - testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation, t), + testAccCheckDRTAccessLogBucketAssociationExists(ctx, resourceName, &drtaccesslogbucketassociation), acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfshield.ResourceDRTAccessLogBucketAssociation, resourceName), ), ExpectNonEmptyPlan: true, @@ -112,7 +112,7 @@ func TestAccShieldDRTAccessLogBucketAssociation_disappears(t *testing.T) { }) } -func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context, t *testing.T) resource.TestCheckFunc { +func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).ShieldConn(ctx) @@ -128,17 +128,15 @@ func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context, t *te return nil } if err != nil { - return nil + return err } if resp != nil { if resp.LogBucketList != nil && len(resp.LogBucketList) > 0 { for _, bucket := range resp.LogBucketList { - if *bucket == rs.Primary.Attributes["log_bucket"] { return create.Error(names.Shield, create.ErrActionCheckingDestroyed, tfshield.ResNameDRTAccessLogBucketAssociation, rs.Primary.ID, errors.New("bucket association not destroyed")) } } - } return nil } @@ -150,7 +148,7 @@ func testAccCheckDRTAccessLogBucketAssociationDestroy(ctx context.Context, t *te } } -func testAccCheckDRTAccessLogBucketAssociationExists(ctx context.Context, name string, drtaccesslogbucketassociation *shield.DescribeDRTAccessOutput, t *testing.T) resource.TestCheckFunc { +func testAccCheckDRTAccessLogBucketAssociationExists(ctx context.Context, name string, drtaccesslogbucketassociation *shield.DescribeDRTAccessOutput) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] @@ -188,7 +186,7 @@ func testAccPreCheckLogBucket(ctx context.Context, t *testing.T) { } } -func testAccDRTAccessLogBucketAssociationConfig_basic(rName string, bucket string, t *testing.T) string { +func testAccDRTAccessLogBucketAssociationConfig_basic(rName string, bucket string) string { return fmt.Sprintf(` data "aws_partition" "current" {} @@ -234,7 +232,7 @@ resource "aws_shield_drt_access_log_bucket_association" "test" { `, rName, bucket) } -func testAccDRTAccessLogBucketAssociationConfig_multibucket(rName string, buckets []string, t *testing.T) string { +func testAccDRTAccessLogBucketAssociationConfig_multibucket(rName string, buckets []string) string { return fmt.Sprintf(` data "aws_partition" "current" {} From f940142947f4215cbae925dc332ec94363afeec8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Sep 2023 13:30:14 -0400 Subject: [PATCH 15/15] Add explicit 'depends_on' to prevent 'The provided role does not have a valid DRT managed policy attached' errors. --- internal/service/shield/drt_access_role_arn_association_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/service/shield/drt_access_role_arn_association_test.go b/internal/service/shield/drt_access_role_arn_association_test.go index 1eaaa68b31a..c2162d52822 100644 --- a/internal/service/shield/drt_access_role_arn_association_test.go +++ b/internal/service/shield/drt_access_role_arn_association_test.go @@ -174,6 +174,8 @@ resource "aws_iam_role_policy_attachment" "test" { resource "aws_shield_drt_access_role_arn_association" "test" { role_arn = aws_iam_role.test.arn + + depends_on = [aws_iam_role_policy_attachment.test] } `, rName) }