From 6b183fec983335d94a3d1946998e30f6935ac9cb Mon Sep 17 00:00:00 2001 From: Siddarth Yuvaraj Date: Mon, 18 Dec 2023 04:09:12 -0500 Subject: [PATCH 01/35] updated the secret manager data source to get the created date of the secret --- internal/service/secretsmanager/secret_data_source.go | 10 ++++++++++ .../service/secretsmanager/secret_data_source_test.go | 2 ++ .../secretsmanager/secret_version_data_source.go | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/internal/service/secretsmanager/secret_data_source.go b/internal/service/secretsmanager/secret_data_source.go index d4b1676d1e1..823c0051361 100644 --- a/internal/service/secretsmanager/secret_data_source.go +++ b/internal/service/secretsmanager/secret_data_source.go @@ -52,6 +52,14 @@ func DataSourceSecret() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "created_date": { + Type: schema.TypeString, + Computed: true, + }, + "last_changed_date": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -99,6 +107,8 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, meta inte d.Set("kms_key_id", output.KmsKeyId) d.Set("name", output.Name) d.Set("policy", "") + d.Set("created_date", aws.String(output.CreatedDate.Format("2006-01-02T15:04:05Z07:00"))) + d.Set("last_changed_date", aws.String(output.LastChangedDate.Format("2006-01-02T15:04:05Z07:00"))) pIn := &secretsmanager.GetResourcePolicyInput{ SecretId: aws.String(d.Id()), diff --git a/internal/service/secretsmanager/secret_data_source_test.go b/internal/service/secretsmanager/secret_data_source_test.go index 1948d255cf4..45db8ff8775 100644 --- a/internal/service/secretsmanager/secret_data_source_test.go +++ b/internal/service/secretsmanager/secret_data_source_test.go @@ -120,6 +120,8 @@ func testAccSecretCheckDataSource(datasourceName, resourceName string) resource. "name", "policy", "tags.#", + "created_date", + "last_changed_date", } for _, attrName := range attrNames { diff --git a/internal/service/secretsmanager/secret_version_data_source.go b/internal/service/secretsmanager/secret_version_data_source.go index 4228b6b4d76..dab294ee5a0 100644 --- a/internal/service/secretsmanager/secret_version_data_source.go +++ b/internal/service/secretsmanager/secret_version_data_source.go @@ -57,6 +57,10 @@ func DataSourceSecretVersion() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "created_date": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -99,6 +103,7 @@ func dataSourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, me d.Set("version_id", output.VersionId) d.Set("secret_binary", string(output.SecretBinary)) d.Set("arn", output.ARN) + d.Set("created_date", aws.String(output.CreatedDate.Format("2006-01-02T15:04:05Z07:00"))) if err := d.Set("version_stages", flex.FlattenStringList(output.VersionStages)); err != nil { return sdkdiag.AppendErrorf(diags, "setting version_stages: %s", err) From eb2652bf10669cfd94a169df287d0a624d83aac3 Mon Sep 17 00:00:00 2001 From: Siddarth Yuvaraj Date: Mon, 18 Dec 2023 08:25:31 -0500 Subject: [PATCH 02/35] updated the secret manager data source to get the created date of the secret and updated the doc --- website/docs/d/secretsmanager_secret.html.markdown | 2 ++ website/docs/d/secretsmanager_secret_version.html.markdown | 1 + 2 files changed, 3 insertions(+) diff --git a/website/docs/d/secretsmanager_secret.html.markdown b/website/docs/d/secretsmanager_secret.html.markdown index 113a86c3da1..afb12fe02f2 100644 --- a/website/docs/d/secretsmanager_secret.html.markdown +++ b/website/docs/d/secretsmanager_secret.html.markdown @@ -43,3 +43,5 @@ This data source exports the following attributes in addition to the arguments a * `id` - ARN of the secret. * `tags` - Tags of the secret. * `policy` - Resource-based policy document that's attached to the secret. +* `created_date` - Created date of the secret. +* `last_changed_date` - Last updated date of the secret. \ No newline at end of file diff --git a/website/docs/d/secretsmanager_secret_version.html.markdown b/website/docs/d/secretsmanager_secret_version.html.markdown index a19c97db6b6..7d61f3f5663 100644 --- a/website/docs/d/secretsmanager_secret_version.html.markdown +++ b/website/docs/d/secretsmanager_secret_version.html.markdown @@ -56,3 +56,4 @@ This data source exports the following attributes in addition to the arguments a * `secret_string` - Decrypted part of the protected secret information that was originally provided as a string. * `secret_binary` - Decrypted part of the protected secret information that was originally provided as a binary. * `version_id` - Unique identifier of this version of the secret. +* `created_date` - Created date of the secret. \ No newline at end of file From 8cbf23b47c70b1d1713d4223e8f6d866c8bd5a55 Mon Sep 17 00:00:00 2001 From: Siddarth Yuvaraj Date: Mon, 18 Dec 2023 09:57:51 -0500 Subject: [PATCH 03/35] updated the doc for secrets manager --- website/docs/d/secretsmanager_secret.html.markdown | 4 ++-- website/docs/d/secretsmanager_secret_version.html.markdown | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/d/secretsmanager_secret.html.markdown b/website/docs/d/secretsmanager_secret.html.markdown index afb12fe02f2..828c875d892 100644 --- a/website/docs/d/secretsmanager_secret.html.markdown +++ b/website/docs/d/secretsmanager_secret.html.markdown @@ -43,5 +43,5 @@ This data source exports the following attributes in addition to the arguments a * `id` - ARN of the secret. * `tags` - Tags of the secret. * `policy` - Resource-based policy document that's attached to the secret. -* `created_date` - Created date of the secret. -* `last_changed_date` - Last updated date of the secret. \ No newline at end of file +* `created_date` - Created date of the secret in UTC. +* `last_changed_date` - Last updated date of the secret in UTC. \ No newline at end of file diff --git a/website/docs/d/secretsmanager_secret_version.html.markdown b/website/docs/d/secretsmanager_secret_version.html.markdown index 7d61f3f5663..ed02ae6e7dc 100644 --- a/website/docs/d/secretsmanager_secret_version.html.markdown +++ b/website/docs/d/secretsmanager_secret_version.html.markdown @@ -56,4 +56,4 @@ This data source exports the following attributes in addition to the arguments a * `secret_string` - Decrypted part of the protected secret information that was originally provided as a string. * `secret_binary` - Decrypted part of the protected secret information that was originally provided as a binary. * `version_id` - Unique identifier of this version of the secret. -* `created_date` - Created date of the secret. \ No newline at end of file +* `created_date` - Created date of the secret in UTC. \ No newline at end of file From 68db4538820f5aaec6892edbe1aaf36df01c5123 Mon Sep 17 00:00:00 2001 From: Oussama Bounaim <1151352+obounaim@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:47:18 +0100 Subject: [PATCH 04/35] Add rotate_immediately option to secret rotation --- internal/service/secretsmanager/secret_rotation.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/service/secretsmanager/secret_rotation.go b/internal/service/secretsmanager/secret_rotation.go index b6be0ce716d..950efc4b282 100644 --- a/internal/service/secretsmanager/secret_rotation.go +++ b/internal/service/secretsmanager/secret_rotation.go @@ -38,6 +38,11 @@ func ResourceSecretRotation() *schema.Resource { Type: schema.TypeBool, Computed: true, }, + "rotate_immediatley": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, "rotation_lambda_arn": { Type: schema.TypeString, Optional: true, @@ -87,6 +92,7 @@ func resourceSecretRotationCreate(ctx context.Context, d *schema.ResourceData, m input := &secretsmanager.RotateSecretInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries + RotateImmediately: aws.Bool(d.Get("rotate_immediatley").(bool)), RotationRules: expandRotationRules(d.Get("rotation_rules").([]interface{})), SecretId: aws.String(secretID), } @@ -149,9 +155,10 @@ func resourceSecretRotationUpdate(ctx context.Context, d *schema.ResourceData, m conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) secretID := d.Get("secret_id").(string) - if d.HasChanges("rotation_lambda_arn", "rotation_rules") { + if d.HasChanges("rotation_lambda_arn", "rotation_rules", "rotate_immediatley") { input := &secretsmanager.RotateSecretInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries + RotateImmediately: aws.Bool(d.Get("rotate_immediatley").(bool)), RotationRules: expandRotationRules(d.Get("rotation_rules").([]interface{})), SecretId: aws.String(secretID), } From 64444959102c1f3dfd64a39525b20182a540bf52 Mon Sep 17 00:00:00 2001 From: Oussama Bounaim <1151352+obounaim@users.noreply.github.com> Date: Thu, 4 Jan 2024 06:20:10 +0100 Subject: [PATCH 05/35] Add changelog entry --- .changelog/35105.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/35105.txt diff --git a/.changelog/35105.txt b/.changelog/35105.txt new file mode 100644 index 00000000000..cb29c5c412a --- /dev/null +++ b/.changelog/35105.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_secretsmanager_secret_rotation: Add `rotate_immediatley` argument. +``` From da33712d3adf04ee51436ebeb8ccf8abf00dd151 Mon Sep 17 00:00:00 2001 From: Oussama Bounaim <1151352+obounaim@users.noreply.github.com> Date: Thu, 4 Jan 2024 06:28:29 +0100 Subject: [PATCH 06/35] Update documentation --- website/docs/r/secretsmanager_secret_rotation.html.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/r/secretsmanager_secret_rotation.html.markdown b/website/docs/r/secretsmanager_secret_rotation.html.markdown index eb8189c8202..7be5ce8c0da 100644 --- a/website/docs/r/secretsmanager_secret_rotation.html.markdown +++ b/website/docs/r/secretsmanager_secret_rotation.html.markdown @@ -38,6 +38,7 @@ To enable automatic secret rotation, the Secrets Manager service requires usage This resource supports the following arguments: * `secret_id` - (Required) Specifies the secret to which you want to add a new version. You can specify either the Amazon Resource Name (ARN) or the friendly name of the secret. The secret must already exist. +* `rotate_immediately` - (Optional) Specifies whether to rotate the secret immediately or wait until the next scheduled rotation window. For secrets that use a Lambda rotation function to rotate, if you don't immediately rotate the secret, Secrets Manager tests the rotation configuration by running the testSecret step (https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_how.html) of the Lambda rotation function. The test creates an AWSPENDING version of the secret and then removes it. Defaults to `false`. * `rotation_lambda_arn` - (Optional) Specifies the ARN of the Lambda function that can rotate the secret. Must be supplied if the secret is not managed by AWS. * `rotation_rules` - (Required) A structure that defines the rotation configuration for this secret. Defined below. From 95f712081fd13063c859b5cb8c871147a22fca3f Mon Sep 17 00:00:00 2001 From: Oussama Bounaim <1151352+obounaim@users.noreply.github.com> Date: Thu, 4 Jan 2024 06:31:12 +0100 Subject: [PATCH 07/35] Fix typo --- .changelog/35105.txt | 2 +- internal/service/secretsmanager/secret_rotation.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.changelog/35105.txt b/.changelog/35105.txt index cb29c5c412a..ff8ac8225ef 100644 --- a/.changelog/35105.txt +++ b/.changelog/35105.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -resource/aws_secretsmanager_secret_rotation: Add `rotate_immediatley` argument. +resource/aws_secretsmanager_secret_rotation: Add `rotate_immediately` argument. ``` diff --git a/internal/service/secretsmanager/secret_rotation.go b/internal/service/secretsmanager/secret_rotation.go index 950efc4b282..5b3c68b0d17 100644 --- a/internal/service/secretsmanager/secret_rotation.go +++ b/internal/service/secretsmanager/secret_rotation.go @@ -38,7 +38,7 @@ func ResourceSecretRotation() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "rotate_immediatley": { + "rotate_immediately": { Type: schema.TypeBool, Optional: true, Default: true, @@ -92,7 +92,7 @@ func resourceSecretRotationCreate(ctx context.Context, d *schema.ResourceData, m input := &secretsmanager.RotateSecretInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries - RotateImmediately: aws.Bool(d.Get("rotate_immediatley").(bool)), + RotateImmediately: aws.Bool(d.Get("rotate_immediately").(bool)), RotationRules: expandRotationRules(d.Get("rotation_rules").([]interface{})), SecretId: aws.String(secretID), } @@ -155,10 +155,10 @@ func resourceSecretRotationUpdate(ctx context.Context, d *schema.ResourceData, m conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) secretID := d.Get("secret_id").(string) - if d.HasChanges("rotation_lambda_arn", "rotation_rules", "rotate_immediatley") { + if d.HasChanges("rotation_lambda_arn", "rotation_rules", "rotate_immediately") { input := &secretsmanager.RotateSecretInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries - RotateImmediately: aws.Bool(d.Get("rotate_immediatley").(bool)), + RotateImmediately: aws.Bool(d.Get("rotate_immediately").(bool)), RotationRules: expandRotationRules(d.Get("rotation_rules").([]interface{})), SecretId: aws.String(secretID), } From 5c919405526e9d288519d7f011deb634a2ad85b4 Mon Sep 17 00:00:00 2001 From: Oussama Bounaim <1151352+obounaim@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:48:04 +0100 Subject: [PATCH 08/35] Add Acc Test aws_secretsmanager_secret_rotation `rotate_immediatley` --- .../secretsmanager/secret_rotation_test.go | 100 +++++++++++++++--- 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/internal/service/secretsmanager/secret_rotation_test.go b/internal/service/secretsmanager/secret_rotation_test.go index fc1d29c1f93..4b46dc1a9b5 100644 --- a/internal/service/secretsmanager/secret_rotation_test.go +++ b/internal/service/secretsmanager/secret_rotation_test.go @@ -39,6 +39,7 @@ func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { testAccCheckSecretRotationExists(ctx, resourceName, &secret), resource.TestCheckResourceAttr(resourceName, "rotation_enabled", "true"), resource.TestCheckResourceAttrPair(resourceName, "rotation_lambda_arn", lambdaFunctionResourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "rotate_immediately", "true"), resource.TestCheckResourceAttr(resourceName, "rotation_rules.#", "1"), resource.TestCheckResourceAttr(resourceName, "rotation_rules.0.automatically_after_days", strconv.Itoa(days)), resource.TestCheckResourceAttr(resourceName, "rotation_rules.0.duration", ""), @@ -46,9 +47,46 @@ func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"rotate_immediately"}, + }, + }, + }) +} + +func TestAccSecretsManagerSecretRotation_rotateImmediately(t *testing.T) { + ctx := acctest.Context(t) + var secret secretsmanager.DescribeSecretOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_secretsmanager_secret_rotation.test" + lambdaFunctionResourceName := "aws_lambda_function.test" + days := 7 + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretRotationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretRotationConfig_rotateImmediately(rName, days), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretRotationExists(ctx, resourceName, &secret), + resource.TestCheckResourceAttr(resourceName, "rotation_enabled", "true"), + resource.TestCheckResourceAttrPair(resourceName, "rotation_lambda_arn", lambdaFunctionResourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "rotate_immediately", "false"), + resource.TestCheckResourceAttr(resourceName, "rotation_rules.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rotation_rules.0.automatically_after_days", strconv.Itoa(days)), + resource.TestCheckResourceAttr(resourceName, "rotation_rules.0.duration", ""), + resource.TestCheckResourceAttr(resourceName, "rotation_rules.0.schedule_expression", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"rotate_immediately"}, }, }, }) @@ -89,9 +127,10 @@ func TestAccSecretsManagerSecretRotation_scheduleExpression(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"rotate_immediately"}, }, }, }) @@ -136,9 +175,10 @@ func TestAccSecretsManagerSecretRotation_scheduleExpressionToDays(t *testing.T) ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"rotate_immediately"}, }, }, }) @@ -180,9 +220,10 @@ func TestAccSecretsManagerSecretRotation_scheduleExpressionHours(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"rotate_immediately"}, }, }, }) @@ -215,9 +256,10 @@ func TestAccSecretsManagerSecretRotation_duration(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"rotate_immediately"}, }, }, }) @@ -362,6 +404,34 @@ resource "aws_secretsmanager_secret_rotation" "test" { `, rName, automaticallyAfterDays)) } +func testAccSecretRotationConfig_rotateImmediately(rName string, automaticallyAfterDays int) string { + return acctest.ConfigCompose( + acctest.ConfigLambdaBase(rName, rName, rName), + testAccSecretRotationConfigBase(rName), + fmt.Sprintf(` +resource "aws_secretsmanager_secret" "test" { + name = %[1]q +} + +resource "aws_secretsmanager_secret_version" "test" { + secret_id = aws_secretsmanager_secret.test.id + secret_string = "test-string" +} + +resource "aws_secretsmanager_secret_rotation" "test" { + secret_id = aws_secretsmanager_secret.test.id + rotation_lambda_arn = aws_lambda_function.test.arn + rotate_immediately = false + + rotation_rules { + automatically_after_days = %[2]d + } + + depends_on = [aws_lambda_permission.test] +} +`, rName, automaticallyAfterDays)) +} + func testAccSecretRotationConfig_scheduleExpression(rName string, scheduleExpression string) string { return acctest.ConfigCompose( acctest.ConfigLambdaBase(rName, rName, rName), From 913ec6ba5e8b34e838a0bb723c5707a327788a71 Mon Sep 17 00:00:00 2001 From: Oussama Bounaim <1151352+obounaim@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:58:05 +0100 Subject: [PATCH 09/35] Remove trailing space --- internal/service/secretsmanager/secret_rotation_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/secretsmanager/secret_rotation_test.go b/internal/service/secretsmanager/secret_rotation_test.go index 4b46dc1a9b5..615ae047401 100644 --- a/internal/service/secretsmanager/secret_rotation_test.go +++ b/internal/service/secretsmanager/secret_rotation_test.go @@ -421,7 +421,7 @@ resource "aws_secretsmanager_secret_version" "test" { resource "aws_secretsmanager_secret_rotation" "test" { secret_id = aws_secretsmanager_secret.test.id rotation_lambda_arn = aws_lambda_function.test.arn - rotate_immediately = false + rotate_immediately = false rotation_rules { automatically_after_days = %[2]d From aa56e35801bbfef75078055beb2c3f1d8ae73f3a Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Sun, 7 Jan 2024 20:18:59 +0100 Subject: [PATCH 10/35] `r/aws_secretsmanager` - migrate to `aws-sdk-go-v2` First draft: - The namevaluesfilters generation is in limbo state --- go.mod | 1 + go.sum | 2 + internal/conns/awsclient_gen.go | 6 +- .../generators/servicefilters/main.go | 2 +- .../namevaluesfilters/service_filters_gen.go | 12 +- .../service_generation_customizations.go | 6 +- internal/service/directconnect/sweep.go | 6 +- internal/service/secretsmanager/errors.go | 14 +++ .../service/secretsmanager/exports_test.go | 10 ++ internal/service/secretsmanager/generate.go | 2 +- .../random_password_data_source.go | 10 +- .../random_password_data_source_test.go | 6 +- internal/service/secretsmanager/secret.go | 116 ++++++++--------- .../secretsmanager/secret_data_source.go | 12 +- .../secretsmanager/secret_data_source_test.go | 10 +- .../service/secretsmanager/secret_policy.go | 32 ++--- .../secretsmanager/secret_policy_test.go | 30 ++--- .../service/secretsmanager/secret_rotation.go | 23 ++-- .../secret_rotation_data_source.go | 2 +- .../secret_rotation_data_source_test.go | 4 +- .../secretsmanager/secret_rotation_test.go | 27 ++-- .../service/secretsmanager/secret_test.go | 29 ++--- .../service/secretsmanager/secret_version.go | 46 +++---- .../secret_version_data_source.go | 15 ++- .../secret_version_data_source_test.go | 8 +- .../secretsmanager/secret_version_test.go | 26 ++-- .../secretsmanager/secrets_data_source.go | 29 ++--- .../secrets_data_source_test.go | 4 +- .../secretsmanager/service_package_gen.go | 17 +-- internal/service/secretsmanager/sweep.go | 117 +++++++++--------- internal/service/secretsmanager/tags_gen.go | 30 ++--- names/data/names_data.csv | 2 +- names/names.go | 1 + 33 files changed, 345 insertions(+), 312 deletions(-) create mode 100644 internal/service/secretsmanager/errors.go create mode 100644 internal/service/secretsmanager/exports_test.go diff --git a/go.mod b/go.mod index 9d699f796f2..ff235419763 100644 --- a/go.mod +++ b/go.mod @@ -88,6 +88,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0 github.com/aws/aws-sdk-go-v2/service/s3control v1.41.8 github.com/aws/aws-sdk-go-v2/service/scheduler v1.6.6 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.26.1 github.com/aws/aws-sdk-go-v2/service/securityhub v1.44.2 github.com/aws/aws-sdk-go-v2/service/securitylake v1.10.6 github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry v1.24.8 diff --git a/go.sum b/go.sum index ab9d0bd5253..45804b2eba9 100644 --- a/go.sum +++ b/go.sum @@ -213,6 +213,8 @@ github.com/aws/aws-sdk-go-v2/service/s3control v1.41.8 h1:sNRLDR2mSZuu+BU6mHbpsV github.com/aws/aws-sdk-go-v2/service/s3control v1.41.8/go.mod h1:fxV+LYjoXZKrMMYSp+UMmgJK/oNxnogfYh12ZcrdbxU= github.com/aws/aws-sdk-go-v2/service/scheduler v1.6.6 h1:UGSUCgzcayABoswjfZPPC7KzQ42jFnbd+7YtbiSK+mw= github.com/aws/aws-sdk-go-v2/service/scheduler v1.6.6/go.mod h1:ZVDwUL35K1x24YFqlUVjFgN1dpHVcfDqrYVa3PKWZlo= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.26.1 h1:Sn3MAV9YeACCULaxNWWYFH1a6G4wYFwBn3/TA5MwE2Q= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.26.1/go.mod h1:qutL00aW8GSo2D0I6UEOqMvRS3ZyuBrOC1BLe5D2jPc= github.com/aws/aws-sdk-go-v2/service/securityhub v1.44.2 h1:uzdslJwui029KDFFmB6a9pzhCDuRVqqdjUlbqKVmNrk= github.com/aws/aws-sdk-go-v2/service/securityhub v1.44.2/go.mod h1:/bd0JTnfysvNRGN27JGDeCco/KMMXOuZaI4wtQ7li38= github.com/aws/aws-sdk-go-v2/service/securitylake v1.10.6 h1:6sj5sZjXF3WsYEMpbaaasZkbhlgCG/zbKxv4DU+8yf8= diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index d69c7428105..46434d2fb2d 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -82,6 +82,7 @@ import ( s3_sdkv2 "github.com/aws/aws-sdk-go-v2/service/s3" s3control_sdkv2 "github.com/aws/aws-sdk-go-v2/service/s3control" scheduler_sdkv2 "github.com/aws/aws-sdk-go-v2/service/scheduler" + secretsmanager_sdkv2 "github.com/aws/aws-sdk-go-v2/service/secretsmanager" securityhub_sdkv2 "github.com/aws/aws-sdk-go-v2/service/securityhub" securitylake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/securitylake" servicecatalogappregistry_sdkv2 "github.com/aws/aws-sdk-go-v2/service/servicecatalogappregistry" @@ -216,7 +217,6 @@ import ( s3outposts_sdkv1 "github.com/aws/aws-sdk-go/service/s3outposts" sagemaker_sdkv1 "github.com/aws/aws-sdk-go/service/sagemaker" schemas_sdkv1 "github.com/aws/aws-sdk-go/service/schemas" - secretsmanager_sdkv1 "github.com/aws/aws-sdk-go/service/secretsmanager" serverlessapplicationrepository_sdkv1 "github.com/aws/aws-sdk-go/service/serverlessapplicationrepository" servicecatalog_sdkv1 "github.com/aws/aws-sdk-go/service/servicecatalog" servicediscovery_sdkv1 "github.com/aws/aws-sdk-go/service/servicediscovery" @@ -1053,8 +1053,8 @@ func (c *AWSClient) SchemasConn(ctx context.Context) *schemas_sdkv1.Schemas { return errs.Must(conn[*schemas_sdkv1.Schemas](ctx, c, names.Schemas, make(map[string]any))) } -func (c *AWSClient) SecretsManagerConn(ctx context.Context) *secretsmanager_sdkv1.SecretsManager { - return errs.Must(conn[*secretsmanager_sdkv1.SecretsManager](ctx, c, names.SecretsManager, make(map[string]any))) +func (c *AWSClient) SecretsManagerClient(ctx context.Context) *secretsmanager_sdkv2.Client { + return errs.Must(client[*secretsmanager_sdkv2.Client](ctx, c, names.SecretsManager, make(map[string]any))) } func (c *AWSClient) SecurityHubClient(ctx context.Context) *securityhub_sdkv2.Client { diff --git a/internal/generate/namevaluesfilters/generators/servicefilters/main.go b/internal/generate/namevaluesfilters/generators/servicefilters/main.go index 6334e0421f0..05ae86ee889 100644 --- a/internal/generate/namevaluesfilters/generators/servicefilters/main.go +++ b/internal/generate/namevaluesfilters/generators/servicefilters/main.go @@ -97,7 +97,7 @@ import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports "github.com/aws/aws-sdk-go/aws" {{- range .SliceServiceNames }} {{- if eq . (. | FilterPackage) }} - "github.com/aws/aws-sdk-go/service/{{ . }}" + "{{ . }}" {{- end }} {{- end }} ) diff --git a/internal/generate/namevaluesfilters/service_filters_gen.go b/internal/generate/namevaluesfilters/service_filters_gen.go index ef29039b458..62a2b4a84c8 100644 --- a/internal/generate/namevaluesfilters/service_filters_gen.go +++ b/internal/generate/namevaluesfilters/service_filters_gen.go @@ -17,7 +17,7 @@ import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" "github.com/aws/aws-sdk-go/service/route53resolver" - "github.com/aws/aws-sdk-go/service/secretsmanager" + secretsmanagertypes "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" ) // []*SERVICE.Filter handling @@ -309,19 +309,19 @@ func (filters NameValuesFilters) Route53resolverFilters() []*route53resolver.Fil } // SecretsmanagerFilters returns secretsmanager service filters. -func (filters NameValuesFilters) SecretsmanagerFilters() []*secretsmanager.Filter { +func (filters NameValuesFilters) SecretsmanagerFilters() []secretsmanagertypes.Filter { m := filters.Map() if len(m) == 0 { return nil } - result := make([]*secretsmanager.Filter, 0, len(m)) + result := make([]secretsmanagertypes.Filter, 0, len(m)) for k, v := range m { - filter := &secretsmanager.Filter{ - Key: aws.String(k), - Values: aws.StringSlice(v), + filter := secretsmanagertypes.Filter{ + Key: secretsmanagertypes.FilterNameStringType(k), + Values: v, } result = append(result, filter) diff --git a/internal/generate/namevaluesfilters/service_generation_customizations.go b/internal/generate/namevaluesfilters/service_generation_customizations.go index 0f57d9385e2..0028d5e49fe 100644 --- a/internal/generate/namevaluesfilters/service_generation_customizations.go +++ b/internal/generate/namevaluesfilters/service_generation_customizations.go @@ -5,11 +5,15 @@ package namevaluesfilters +import "fmt" + // ServiceFilterPackage determines the service filter type package. func ServiceFilterPackage(serviceName string) string { switch serviceName { + case "secretsmanager": + return fmt.Sprintf("github.com/aws/aws-sdk-go-v2/service/%s/types", serviceName) default: - return serviceName + return "github.com/aws/aws-sdk-go/service/" + serviceName } } diff --git a/internal/service/directconnect/sweep.go b/internal/service/directconnect/sweep.go index cff0db50387..d9c884a4384 100644 --- a/internal/service/directconnect/sweep.go +++ b/internal/service/directconnect/sweep.go @@ -7,10 +7,10 @@ import ( "fmt" "log" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/directconnect" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" @@ -459,7 +459,7 @@ func sweepMacSecKeys(region string) error { // key when deleting the MACsec key association. The only option to // clean up the dangling resource is to use Secrets Manager to delete // the MACsec key secret. - smConn := client.SecretsManagerConn(ctx) + smConn := client.SecretsManagerClient(ctx) dxInput := &directconnect.DescribeConnectionsInput{} var sweeperErrs *multierror.Error @@ -495,7 +495,7 @@ func sweepMacSecKeys(region string) error { } log.Printf("[DEBUG] Deleting MACSec secret key: %s", *input.SecretId) - _, err := smConn.DeleteSecretWithContext(ctx, input) + _, err := smConn.DeleteSecret(ctx, input) if err != nil { sweeperErr := fmt.Errorf("error deleting MACsec Secret (%s): %w", arn, err) diff --git a/internal/service/secretsmanager/errors.go b/internal/service/secretsmanager/errors.go new file mode 100644 index 00000000000..5d8be3cca74 --- /dev/null +++ b/internal/service/secretsmanager/errors.go @@ -0,0 +1,14 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package secretsmanager + +import ( + "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" +) + +var ( + errCodeMalformedPolicyDocumentException = (*types.MalformedPolicyDocumentException)(nil).ErrorCode() + errCodeResourceNotFoundException = (*types.ResourceNotFoundException)(nil).ErrorCode() + errCodeInvalidRequestException = (*types.InvalidRequestException)(nil).ErrorCode() +) diff --git a/internal/service/secretsmanager/exports_test.go b/internal/service/secretsmanager/exports_test.go new file mode 100644 index 00000000000..b820fd6c66e --- /dev/null +++ b/internal/service/secretsmanager/exports_test.go @@ -0,0 +1,10 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package secretsmanager + +// Exports for use in tests only. +var ( + ErrCodeResourceNotFoundException = errCodeResourceNotFoundException + ErrCodeInvalidRequestException = errCodeInvalidRequestException +) diff --git a/internal/service/secretsmanager/generate.go b/internal/service/secretsmanager/generate.go index c1b1ca83239..7248f771d5c 100644 --- a/internal/service/secretsmanager/generate.go +++ b/internal/service/secretsmanager/generate.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/tags/main.go -ListTagsInIDElem=SecretId -ServiceTagsSlice -TagInIDElem=SecretId -UpdateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTagsInIDElem=SecretId -ServiceTagsSlice -TagInIDElem=SecretId -UpdateTags //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. diff --git a/internal/service/secretsmanager/random_password_data_source.go b/internal/service/secretsmanager/random_password_data_source.go index 839de8b39ff..fad43983092 100644 --- a/internal/service/secretsmanager/random_password_data_source.go +++ b/internal/service/secretsmanager/random_password_data_source.go @@ -6,8 +6,8 @@ package secretsmanager import ( "context" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -64,7 +64,7 @@ func DataSourceRandomPassword() *schema.Resource { func dataSourceRandomPasswordRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) var excludeCharacters string if v, ok := d.GetOk("exclude_characters"); ok { @@ -110,12 +110,12 @@ func dataSourceRandomPasswordRead(ctx context.Context, d *schema.ResourceData, m RequireEachIncludedType: aws.Bool(requireEachIncludedType), } - output, err := conn.GetRandomPasswordWithContext(ctx, input) + output, err := conn.GetRandomPassword(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Get Random Password: %s", err) } - d.SetId(aws.StringValue(output.RandomPassword)) + d.SetId(aws.ToString(output.RandomPassword)) d.Set("random_password", output.RandomPassword) return diags diff --git a/internal/service/secretsmanager/random_password_data_source_test.go b/internal/service/secretsmanager/random_password_data_source_test.go index f14c46e92a3..41888f7c480 100644 --- a/internal/service/secretsmanager/random_password_data_source_test.go +++ b/internal/service/secretsmanager/random_password_data_source_test.go @@ -8,10 +8,10 @@ import ( "testing" "unicode" - "github.com/aws/aws-sdk-go/service/secretsmanager" "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/names" ) func TestAccSecretsManagerRandomPasswordDataSource_basic(t *testing.T) { @@ -20,7 +20,7 @@ func TestAccSecretsManagerRandomPasswordDataSource_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { @@ -39,7 +39,7 @@ func TestAccSecretsManagerRandomPasswordDataSource_exclude(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { diff --git a/internal/service/secretsmanager/secret.go b/internal/service/secretsmanager/secret.go index 97e0da3fac8..a53d2c9f009 100644 --- a/internal/service/secretsmanager/secret.go +++ b/internal/service/secretsmanager/secret.go @@ -11,9 +11,10 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" @@ -22,6 +23,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "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/internal/errs/sdkdiag" tfiam "github.com/hashicorp/terraform-provider-aws/internal/service/iam" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -139,13 +141,13 @@ func ResourceSecret() *schema.Resource { func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretName := create.Name(d.Get("name").(string), d.Get("name_prefix").(string)) input := &secretsmanager.CreateSecretInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries Description: aws.String(d.Get("description").(string)), - ForceOverwriteReplicaSecret: aws.Bool(d.Get("force_overwrite_replica_secret").(bool)), + ForceOverwriteReplicaSecret: d.Get("force_overwrite_replica_secret").(bool), Name: aws.String(secretName), Tags: getTagsIn(ctx), } @@ -164,11 +166,11 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte var output *secretsmanager.CreateSecretOutput err := retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { var err error - output, err = conn.CreateSecretWithContext(ctx, input) + output, err = conn.CreateSecret(ctx, input) // Temporarily retry on these errors to support immediate secret recreation: // InvalidRequestException: You can’t perform this operation on the secret because it was deleted. // InvalidRequestException: You can't create this secret because a secret with this name is already scheduled for deletion. - if tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "scheduled for deletion") || tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "was deleted") { + if errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "scheduled for deletion") || errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "was deleted") { return retry.RetryableError(err) } if err != nil { @@ -177,13 +179,13 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte return nil }) if tfresource.TimedOut(err) { - output, err = conn.CreateSecretWithContext(ctx, input) + output, err = conn.CreateSecret(ctx, input) } if err != nil { return sdkdiag.AppendErrorf(diags, "creating Secrets Manager Secret: %s", err) } - d.SetId(aws.StringValue(output.ARN)) + d.SetId(aws.ToString(output.ARN)) if v, ok := d.GetOk("policy"); ok && v.(string) != "" && v.(string) != "{}" { policy, err := structure.NormalizeJsonString(v.(string)) @@ -197,8 +199,8 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte } err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { - _, err := conn.PutResourcePolicyWithContext(ctx, input) - if tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeMalformedPolicyDocumentException, + _, err := conn.PutResourcePolicy(ctx, input) + if errs.IsAErrorMessageContains[*types.MalformedPolicyDocumentException](err, "This resource policy contains an unsupported principal") { return retry.RetryableError(err) } @@ -208,7 +210,7 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte return nil }) if tfresource.TimedOut(err) { - _, err = conn.PutResourcePolicyWithContext(ctx, input) + _, err = conn.PutResourcePolicy(ctx, input) } if err != nil { return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret %q policy: %s", d.Id(), err) @@ -220,7 +222,7 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, PropagationTimeout, func() (interface{}, error) { return FindSecretByID(ctx, conn, d.Id()) @@ -242,7 +244,7 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf d.Set("description", output.Description) d.Set("kms_key_id", output.KmsKeyId) d.Set("name", output.Name) - d.Set("name_prefix", create.NamePrefixFromName(aws.StringValue(output.Name))) + d.Set("name_prefix", create.NamePrefixFromName(aws.ToString(output.Name))) if err := d.Set("replica", flattenSecretReplicas(output.ReplicationStatus)); err != nil { return sdkdiag.AppendErrorf(diags, "setting replica: %s", err) @@ -251,7 +253,7 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf var policy *secretsmanager.GetResourcePolicyOutput err = tfresource.Retry(ctx, PropagationTimeout, func() *retry.RetryError { var err error - policy, err = conn.GetResourcePolicyWithContext(ctx, &secretsmanager.GetResourcePolicyInput{ + policy, err = conn.GetResourcePolicy(ctx, &secretsmanager.GetResourcePolicyInput{ SecretId: aws.String(d.Id()), }) if err != nil { @@ -259,7 +261,7 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf } if policy.ResourcePolicy != nil { - valid, err := tfiam.PolicyHasValidAWSPrincipals(aws.StringValue(policy.ResourcePolicy)) + valid, err := tfiam.PolicyHasValidAWSPrincipals(aws.ToString(policy.ResourcePolicy)) if err != nil { return retry.NonRetryableError(err) } @@ -275,7 +277,7 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf if err != nil { return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s) policy: %s", d.Id(), err) } else if v := policy.ResourcePolicy; v != nil { - policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.StringValue(v)) + policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.ToString(v)) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s): %s", d.Id(), err) } @@ -292,7 +294,7 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) if d.HasChange("replica") { o, n := d.GetChange("replica") @@ -325,7 +327,7 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte } log.Printf("[DEBUG] Updating Secrets Manager Secret: %s", input) - _, err := conn.UpdateSecretWithContext(ctx, input) + _, err := conn.UpdateSecret(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret (%s): %s", d.Id(), err) @@ -347,16 +349,16 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte log.Printf("[DEBUG] Setting Secrets Manager Secret resource policy: %s", input) _, err = tfresource.RetryWhenAWSErrMessageContains(ctx, PropagationTimeout, func() (interface{}, error) { - return conn.PutResourcePolicyWithContext(ctx, input) + return conn.PutResourcePolicy(ctx, input) }, - secretsmanager.ErrCodeMalformedPolicyDocumentException, "This resource policy contains an unsupported principal") + errCodeMalformedPolicyDocumentException, "This resource policy contains an unsupported principal") if err != nil { return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret (%s) policy: %s", d.Id(), err) } } else { log.Printf("[DEBUG] Removing Secrets Manager Secret policy: %s", d.Id()) - _, err := conn.DeleteResourcePolicyWithContext(ctx, &secretsmanager.DeleteResourcePolicyInput{ + _, err := conn.DeleteResourcePolicy(ctx, &secretsmanager.DeleteResourcePolicyInput{ SecretId: aws.String(d.Id()), }) @@ -371,7 +373,7 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) if v, ok := d.GetOk("replica"); ok && v.(*schema.Set).Len() > 0 { err := removeSecretReplicas(ctx, conn, d.Id(), v.(*schema.Set).List()) @@ -393,9 +395,9 @@ func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta inte } log.Printf("[DEBUG] Deleting Secrets Manager Secret: %s", d.Id()) - _, err := conn.DeleteSecretWithContext(ctx, input) + _, err := conn.DeleteSecret(ctx, input) - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return diags } @@ -414,7 +416,7 @@ func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta inte return diags } -func removeSecretReplicas(ctx context.Context, conn *secretsmanager.SecretsManager, id string, tfList []interface{}) error { +func removeSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id string, tfList []interface{}) error { if len(tfList) == 0 { return nil } @@ -435,14 +437,14 @@ func removeSecretReplicas(ctx context.Context, conn *secretsmanager.SecretsManag regions = append(regions, tfMap["region"].(string)) } - input.RemoveReplicaRegions = aws.StringSlice(regions) + input.RemoveReplicaRegions = regions log.Printf("[DEBUG] Removing Secrets Manager Secret Replicas: %s", input) - _, err := conn.RemoveRegionsFromReplicationWithContext(ctx, input) + _, err := conn.RemoveRegionsFromReplication(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return nil } @@ -452,30 +454,26 @@ func removeSecretReplicas(ctx context.Context, conn *secretsmanager.SecretsManag return nil } -func addSecretReplicas(ctx context.Context, conn *secretsmanager.SecretsManager, id string, forceOverwrite bool, tfList []interface{}) error { +func addSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id string, forceOverwrite bool, tfList []interface{}) error { if len(tfList) == 0 { return nil } input := &secretsmanager.ReplicateSecretToRegionsInput{ SecretId: aws.String(id), - ForceOverwriteReplicaSecret: aws.Bool(forceOverwrite), + ForceOverwriteReplicaSecret: forceOverwrite, AddReplicaRegions: expandSecretReplicas(tfList), } log.Printf("[DEBUG] Removing Secrets Manager Secret Replica: %s", input) - _, err := conn.ReplicateSecretToRegionsWithContext(ctx, input) + _, err := conn.ReplicateSecretToRegions(ctx, input) return err } -func expandSecretReplica(tfMap map[string]interface{}) *secretsmanager.ReplicaRegionType { - if tfMap == nil { - return nil - } - - apiObject := &secretsmanager.ReplicaRegionType{} +func expandSecretReplica(tfMap map[string]interface{}) types.ReplicaRegionType { + apiObject := types.ReplicaRegionType{} if v, ok := tfMap["kms_key_id"].(string); ok && v != "" { apiObject.KmsKeyId = aws.String(v) @@ -488,12 +486,12 @@ func expandSecretReplica(tfMap map[string]interface{}) *secretsmanager.ReplicaRe return apiObject } -func expandSecretReplicas(tfList []interface{}) []*secretsmanager.ReplicaRegionType { +func expandSecretReplicas(tfList []interface{}) []types.ReplicaRegionType { if len(tfList) == 0 { return nil } - var apiObjects []*secretsmanager.ReplicaRegionType + var apiObjects []types.ReplicaRegionType for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) @@ -502,49 +500,45 @@ func expandSecretReplicas(tfList []interface{}) []*secretsmanager.ReplicaRegionT continue } - apiObject := expandSecretReplica(tfMap) - - if apiObject == nil { + if tfMap == nil { continue } + apiObject := expandSecretReplica(tfMap) + apiObjects = append(apiObjects, apiObject) } return apiObjects } -func flattenSecretReplica(apiObject *secretsmanager.ReplicationStatusType) map[string]interface{} { - if apiObject == nil { - return nil - } - +func flattenSecretReplica(apiObject types.ReplicationStatusType) map[string]interface{} { tfMap := map[string]interface{}{} if v := apiObject.KmsKeyId; v != nil { - tfMap["kms_key_id"] = aws.StringValue(v) + tfMap["kms_key_id"] = aws.ToString(v) } if v := apiObject.LastAccessedDate; v != nil { - tfMap["last_accessed_date"] = aws.TimeValue(v).Format(time.RFC3339) + tfMap["last_accessed_date"] = aws.ToTime(v).Format(time.RFC3339) } if v := apiObject.Region; v != nil { - tfMap["region"] = aws.StringValue(v) + tfMap["region"] = aws.ToString(v) } - if v := apiObject.Status; v != nil { - tfMap["status"] = aws.StringValue(v) + if v := apiObject.Status; v != "" { + tfMap["status"] = v } if v := apiObject.StatusMessage; v != nil { - tfMap["status_message"] = aws.StringValue(v) + tfMap["status_message"] = aws.ToString(v) } return tfMap } -func flattenSecretReplicas(apiObjects []*secretsmanager.ReplicationStatusType) []interface{} { +func flattenSecretReplicas(apiObjects []types.ReplicationStatusType) []interface{} { if len(apiObjects) == 0 { return nil } @@ -552,10 +546,6 @@ func flattenSecretReplicas(apiObjects []*secretsmanager.ReplicationStatusType) [ var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - tfList = append(tfList, flattenSecretReplica(apiObject)) } @@ -578,10 +568,10 @@ func secretReplicaHash(v interface{}) int { return create.StringHashcode(buf.String()) } -func findSecret(ctx context.Context, conn *secretsmanager.SecretsManager, input *secretsmanager.DescribeSecretInput) (*secretsmanager.DescribeSecretOutput, error) { - output, err := conn.DescribeSecretWithContext(ctx, input) +func findSecret(ctx context.Context, conn *secretsmanager.Client, input *secretsmanager.DescribeSecretInput) (*secretsmanager.DescribeSecretOutput, error) { + output, err := conn.DescribeSecret(ctx, input) - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -599,7 +589,7 @@ func findSecret(ctx context.Context, conn *secretsmanager.SecretsManager, input return output, nil } -func FindSecretByID(ctx context.Context, conn *secretsmanager.SecretsManager, id string) (*secretsmanager.DescribeSecretOutput, error) { +func FindSecretByID(ctx context.Context, conn *secretsmanager.Client, id string) (*secretsmanager.DescribeSecretOutput, error) { input := &secretsmanager.DescribeSecretInput{ SecretId: aws.String(id), } diff --git a/internal/service/secretsmanager/secret_data_source.go b/internal/service/secretsmanager/secret_data_source.go index d4b1676d1e1..5cdf3779b70 100644 --- a/internal/service/secretsmanager/secret_data_source.go +++ b/internal/service/secretsmanager/secret_data_source.go @@ -7,9 +7,9 @@ import ( "context" "log" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" @@ -58,7 +58,7 @@ func DataSourceSecret() *schema.Resource { func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig var secretID string @@ -81,9 +81,9 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, meta inte } log.Printf("[DEBUG] Reading Secrets Manager Secret: %s", input) - output, err := conn.DescribeSecretWithContext(ctx, input) + output, err := conn.DescribeSecret(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q not found", secretID) } return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret: %s", err) @@ -104,7 +104,7 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, meta inte SecretId: aws.String(d.Id()), } log.Printf("[DEBUG] Reading Secrets Manager Secret policy: %s", pIn) - pOut, err := conn.GetResourcePolicyWithContext(ctx, pIn) + pOut, err := conn.GetResourcePolicy(ctx, pIn) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret policy: %s", err) } diff --git a/internal/service/secretsmanager/secret_data_source_test.go b/internal/service/secretsmanager/secret_data_source_test.go index 1948d255cf4..412943ca96a 100644 --- a/internal/service/secretsmanager/secret_data_source_test.go +++ b/internal/service/secretsmanager/secret_data_source_test.go @@ -8,18 +8,18 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/secretsmanager" 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/names" ) func TestAccSecretsManagerSecretDataSource_basic(t *testing.T) { ctx := acctest.Context(t) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { @@ -46,7 +46,7 @@ func TestAccSecretsManagerSecretDataSource_arn(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { @@ -67,7 +67,7 @@ func TestAccSecretsManagerSecretDataSource_name(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { @@ -88,7 +88,7 @@ func TestAccSecretsManagerSecretDataSource_policy(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { diff --git a/internal/service/secretsmanager/secret_policy.go b/internal/service/secretsmanager/secret_policy.go index 5c4f53d075f..e2bb505343b 100644 --- a/internal/service/secretsmanager/secret_policy.go +++ b/internal/service/secretsmanager/secret_policy.go @@ -7,9 +7,9 @@ import ( "context" "log" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -60,7 +60,7 @@ func ResourceSecretPolicy() *schema.Resource { func resourceSecretPolicyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) policy, err := structure.NormalizeJsonString(d.Get("policy").(string)) if err != nil { @@ -81,8 +81,8 @@ func resourceSecretPolicyCreate(ctx context.Context, d *schema.ResourceData, met err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { var err error - output, err = conn.PutResourcePolicyWithContext(ctx, input) - if tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeMalformedPolicyDocumentException, + output, err = conn.PutResourcePolicy(ctx, input) + if tfawserr.ErrMessageContains(err, errCodeMalformedPolicyDocumentException, "This resource policy contains an unsupported principal") { return retry.RetryableError(err) } @@ -92,7 +92,7 @@ func resourceSecretPolicyCreate(ctx context.Context, d *schema.ResourceData, met return nil }) if tfresource.TimedOut(err) { - output, err = conn.PutResourcePolicyWithContext(ctx, input) + output, err = conn.PutResourcePolicy(ctx, input) } if err != nil { return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret %q policy: %s", d.Id(), err) @@ -105,17 +105,17 @@ func resourceSecretPolicyCreate(ctx context.Context, d *schema.ResourceData, met func resourceSecretPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) input := &secretsmanager.GetResourcePolicyInput{ SecretId: aws.String(d.Id()), } outputRaw, err := tfresource.RetryWhenNotFound(ctx, PropagationTimeout, func() (interface{}, error) { - return conn.GetResourcePolicyWithContext(ctx, input) + return conn.GetResourcePolicy(ctx, input) }) - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { log.Printf("[WARN] Secrets Manager Secret Policy (%s) not found, removing from state", d.Id()) d.SetId("") return diags @@ -148,7 +148,7 @@ func resourceSecretPolicyRead(ctx context.Context, d *schema.ResourceData, meta func resourceSecretPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) if d.HasChanges("policy", "block_public_policy") { policy, err := structure.NormalizeJsonString(d.Get("policy").(string)) @@ -163,8 +163,8 @@ func resourceSecretPolicyUpdate(ctx context.Context, d *schema.ResourceData, met log.Printf("[DEBUG] Setting Secrets Manager Secret resource policy; %#v", input) err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { - _, err := conn.PutResourcePolicyWithContext(ctx, input) - if tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeMalformedPolicyDocumentException, + _, err := conn.PutResourcePolicy(ctx, input) + if tfawserr.ErrMessageContains(err, errCodeMalformedPolicyDocumentException, "This resource policy contains an unsupported principal") { return retry.RetryableError(err) } @@ -174,7 +174,7 @@ func resourceSecretPolicyUpdate(ctx context.Context, d *schema.ResourceData, met return nil }) if tfresource.TimedOut(err) { - _, err = conn.PutResourcePolicyWithContext(ctx, input) + _, err = conn.PutResourcePolicy(ctx, input) } if err != nil { return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret %q policy: %s", d.Id(), err) @@ -186,16 +186,16 @@ func resourceSecretPolicyUpdate(ctx context.Context, d *schema.ResourceData, met func resourceSecretPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) input := &secretsmanager.DeleteResourcePolicyInput{ SecretId: aws.String(d.Id()), } log.Printf("[DEBUG] Removing Secrets Manager Secret policy: %#v", input) - _, err := conn.DeleteResourcePolicyWithContext(ctx, input) + _, err := conn.DeleteResourcePolicy(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return diags } return sdkdiag.AppendErrorf(diags, "removing Secrets Manager Secret %q policy: %s", d.Id(), err) diff --git a/internal/service/secretsmanager/secret_policy_test.go b/internal/service/secretsmanager/secret_policy_test.go index 16824737975..c97463ebbb6 100644 --- a/internal/service/secretsmanager/secret_policy_test.go +++ b/internal/service/secretsmanager/secret_policy_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -19,7 +19,9 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfsecretsmanager "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" + tfsm "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccSecretsManagerSecretPolicy_basic(t *testing.T) { @@ -30,7 +32,7 @@ func TestAccSecretsManagerSecretPolicy_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretPolicyDestroy(ctx), Steps: []resource.TestStep{ @@ -68,7 +70,7 @@ func TestAccSecretsManagerSecretPolicy_blockPublicPolicy(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretPolicyDestroy(ctx), Steps: []resource.TestStep{ @@ -111,7 +113,7 @@ func TestAccSecretsManagerSecretPolicy_disappears(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretPolicyDestroy(ctx), Steps: []resource.TestStep{ @@ -129,7 +131,7 @@ func TestAccSecretsManagerSecretPolicy_disappears(t *testing.T) { func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_secretsmanager_secret_policy" { @@ -144,7 +146,7 @@ func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc err := retry.RetryContext(ctx, tfsecretsmanager.PropagationTimeout, func() *retry.RetryError { var err error - output, err = conn.DescribeSecretWithContext(ctx, secretInput) + output, err = conn.DescribeSecret(ctx, secretInput) if err != nil { return retry.NonRetryableError(err) @@ -158,10 +160,10 @@ func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc }) if tfresource.TimedOut(err) { - output, err = conn.DescribeSecretWithContext(ctx, secretInput) + output, err = conn.DescribeSecret(ctx, secretInput) } - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, tfsm.ErrCodeResourceNotFoundException) { continue } @@ -177,10 +179,10 @@ func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc SecretId: aws.String(rs.Primary.ID), } - _, err = conn.GetResourcePolicyWithContext(ctx, input) + _, err = conn.GetResourcePolicy(ctx, input) - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) || - tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, + if tfawserr.ErrCodeEquals(err, tfsm.ErrCodeResourceNotFoundException) || + tfawserr.ErrMessageContains(err, tfsm.ErrCodeInvalidRequestException, "You can't perform this operation on the secret because it was marked for deletion.") { continue } @@ -201,12 +203,12 @@ func testAccCheckSecretPolicyExists(ctx context.Context, resourceName string, po return fmt.Errorf("Not found: %s", resourceName) } - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) input := &secretsmanager.GetResourcePolicyInput{ SecretId: aws.String(rs.Primary.ID), } - output, err := conn.GetResourcePolicyWithContext(ctx, input) + output, err := conn.GetResourcePolicy(ctx, input) if err != nil { return err diff --git a/internal/service/secretsmanager/secret_rotation.go b/internal/service/secretsmanager/secret_rotation.go index b6be0ce716d..0f0cedd1fef 100644 --- a/internal/service/secretsmanager/secret_rotation.go +++ b/internal/service/secretsmanager/secret_rotation.go @@ -9,8 +9,9 @@ import ( "time" "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -82,7 +83,7 @@ func ResourceSecretRotation() *schema.Resource { func resourceSecretRotationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID := d.Get("secret_id").(string) input := &secretsmanager.RotateSecretInput{ @@ -97,7 +98,7 @@ func resourceSecretRotationCreate(ctx context.Context, d *schema.ResourceData, m // AccessDeniedException: Secrets Manager cannot invoke the specified Lambda function. outputRaw, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, 1*time.Minute, func() (interface{}, error) { - return conn.RotateSecretWithContext(ctx, input) + return conn.RotateSecret(ctx, input) }, "AccessDeniedException") if err != nil { @@ -111,7 +112,7 @@ func resourceSecretRotationCreate(ctx context.Context, d *schema.ResourceData, m func resourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, PropagationTimeout, func() (interface{}, error) { return FindSecretByID(ctx, conn, d.Id()) @@ -146,7 +147,7 @@ func resourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, met func resourceSecretRotationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID := d.Get("secret_id").(string) if d.HasChanges("rotation_lambda_arn", "rotation_rules") { @@ -162,7 +163,7 @@ func resourceSecretRotationUpdate(ctx context.Context, d *schema.ResourceData, m // AccessDeniedException: Secrets Manager cannot invoke the specified Lambda function. _, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, 1*time.Minute, func() (interface{}, error) { - return conn.RotateSecretWithContext(ctx, input) + return conn.RotateSecret(ctx, input) }, "AccessDeniedException") if err != nil { @@ -175,9 +176,9 @@ func resourceSecretRotationUpdate(ctx context.Context, d *schema.ResourceData, m func resourceSecretRotationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - _, err := conn.CancelRotateSecretWithContext(ctx, &secretsmanager.CancelRotateSecretInput{ + _, err := conn.CancelRotateSecret(ctx, &secretsmanager.CancelRotateSecretInput{ SecretId: aws.String(d.Get("secret_id").(string)), }) @@ -188,11 +189,11 @@ func resourceSecretRotationDelete(ctx context.Context, d *schema.ResourceData, m return diags } -func expandRotationRules(l []interface{}) *secretsmanager.RotationRulesType { +func expandRotationRules(l []interface{}) *types.RotationRulesType { if len(l) == 0 { return nil } - rules := &secretsmanager.RotationRulesType{} + rules := &types.RotationRulesType{} tfMap := l[0].(map[string]interface{}) @@ -211,7 +212,7 @@ func expandRotationRules(l []interface{}) *secretsmanager.RotationRulesType { return rules } -func flattenRotationRules(rules *secretsmanager.RotationRulesType) []interface{} { +func flattenRotationRules(rules *types.RotationRulesType) []interface{} { if rules == nil { return nil } diff --git a/internal/service/secretsmanager/secret_rotation_data_source.go b/internal/service/secretsmanager/secret_rotation_data_source.go index 8ed3b4457fc..e059517fee3 100644 --- a/internal/service/secretsmanager/secret_rotation_data_source.go +++ b/internal/service/secretsmanager/secret_rotation_data_source.go @@ -59,7 +59,7 @@ func DataSourceSecretRotation() *schema.Resource { func dataSourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID := d.Get("secret_id").(string) output, err := FindSecretByID(ctx, conn, secretID) diff --git a/internal/service/secretsmanager/secret_rotation_data_source_test.go b/internal/service/secretsmanager/secret_rotation_data_source_test.go index 30d522f97a8..d813a4d4610 100644 --- a/internal/service/secretsmanager/secret_rotation_data_source_test.go +++ b/internal/service/secretsmanager/secret_rotation_data_source_test.go @@ -8,10 +8,10 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/secretsmanager" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccSecretsManagerSecretRotationDataSource_basic(t *testing.T) { @@ -22,7 +22,7 @@ func TestAccSecretsManagerSecretRotationDataSource_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { diff --git a/internal/service/secretsmanager/secret_rotation_test.go b/internal/service/secretsmanager/secret_rotation_test.go index fc1d29c1f93..d4e7de859b3 100644 --- a/internal/service/secretsmanager/secret_rotation_test.go +++ b/internal/service/secretsmanager/secret_rotation_test.go @@ -9,8 +9,8 @@ import ( "strconv" "testing" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" tfsecretsmanager "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { @@ -29,7 +30,7 @@ func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { days := 7 resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretRotationDestroy(ctx), Steps: []resource.TestStep{ @@ -64,7 +65,7 @@ func TestAccSecretsManagerSecretRotation_scheduleExpression(t *testing.T) { scheduleExpression02 := "rate(10 days)" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretRotationDestroy(ctx), Steps: []resource.TestStep{ @@ -109,7 +110,7 @@ func TestAccSecretsManagerSecretRotation_scheduleExpressionToDays(t *testing.T) ) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretRotationDestroy(ctx), Steps: []resource.TestStep{ @@ -154,7 +155,7 @@ func TestAccSecretsManagerSecretRotation_scheduleExpressionHours(t *testing.T) { scheduleExpression02 := "rate(10 hours)" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretRotationDestroy(ctx), Steps: []resource.TestStep{ @@ -199,7 +200,7 @@ func TestAccSecretsManagerSecretRotation_duration(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretRotationDestroy(ctx), Steps: []resource.TestStep{ @@ -225,7 +226,7 @@ func TestAccSecretsManagerSecretRotation_duration(t *testing.T) { func testAccCheckSecretRotationDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_secretsmanager_secret_rotation" { @@ -264,7 +265,7 @@ func testAccCheckSecretRotationExists(ctx context.Context, n string, v *secretsm return fmt.Errorf("No Secrets Manager Secret Rotation ID is set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) output, err := tfsecretsmanager.FindSecretByID(ctx, conn, rs.Primary.ID) @@ -284,30 +285,30 @@ func testAccCheckSecretRotationExists(ctx context.Context, n string, v *secretsm func testSecretValueIsCurrent(ctx context.Context, rName string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) // Write secret value to clear in-rotation state, otherwise updating the secret rotation // will fail with "A previous rotation isn't complete. That rotation will be reattempted." put_secret_input := &secretsmanager.PutSecretValueInput{ SecretId: aws.String(rName), SecretString: aws.String("secret-value"), } - _, err := conn.PutSecretValueWithContext(ctx, put_secret_input) + _, err := conn.PutSecretValue(ctx, put_secret_input) if err != nil { return err } input := &secretsmanager.DescribeSecretInput{ SecretId: aws.String(rName), } - output, err := conn.DescribeSecretWithContext(ctx, input) + output, err := conn.DescribeSecret(ctx, input) if err != nil { return err } else { // Ensure that the current version of the secret is in the AWSCURRENT stage for _, stage := range output.VersionIdsToStages { - if *stage[0] == "AWSCURRENT" { + if stage[0] == "AWSCURRENT" { return nil } else { - return fmt.Errorf("Secret version is not in AWSCURRENT stage: %s", *stage[0]) + return fmt.Errorf("Secret version is not in AWSCURRENT stage: %s", stage[0]) } } return nil diff --git a/internal/service/secretsmanager/secret_test.go b/internal/service/secretsmanager/secret_test.go index 607a392a098..28809c7afb6 100644 --- a/internal/service/secretsmanager/secret_test.go +++ b/internal/service/secretsmanager/secret_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/secretsmanager" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" tfsecretsmanager "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccSecretsManagerSecret_basic(t *testing.T) { @@ -27,7 +28,7 @@ func TestAccSecretsManagerSecret_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -62,7 +63,7 @@ func TestAccSecretsManagerSecret_withNamePrefix(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -92,7 +93,7 @@ func TestAccSecretsManagerSecret_description(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -128,7 +129,7 @@ func TestAccSecretsManagerSecret_basicReplica(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t); acctest.PreCheckMultipleRegion(t, 2) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5FactoriesMultipleRegions(ctx, t, 2), CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -152,7 +153,7 @@ func TestAccSecretsManagerSecret_overwriteReplica(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t); acctest.PreCheckMultipleRegion(t, 3) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5FactoriesMultipleRegions(ctx, t, 3), CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -189,7 +190,7 @@ func TestAccSecretsManagerSecret_kmsKeyID(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -225,7 +226,7 @@ func TestAccSecretsManagerSecret_RecoveryWindowInDays_recreate(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -262,7 +263,7 @@ func TestAccSecretsManagerSecret_tags(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -309,7 +310,7 @@ func TestAccSecretsManagerSecret_policy(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ @@ -344,7 +345,7 @@ func TestAccSecretsManagerSecret_policy(t *testing.T) { func testAccCheckSecretDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_secretsmanager_secret" { @@ -379,7 +380,7 @@ func testAccCheckSecretExists(ctx context.Context, n string, v *secretsmanager.D return fmt.Errorf("No Secrets Manager Secret ID is set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) output, err := tfsecretsmanager.FindSecretByID(ctx, conn, rs.Primary.ID) @@ -394,11 +395,11 @@ func testAccCheckSecretExists(ctx context.Context, n string, v *secretsmanager.D } func testAccPreCheck(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) input := &secretsmanager.ListSecretsInput{} - _, err := conn.ListSecretsWithContext(ctx, input) + _, err := conn.ListSecrets(ctx, input) if acctest.PreCheckSkipError(err) { t.Skipf("skipping acceptance testing: %s", err) diff --git a/internal/service/secretsmanager/secret_version.go b/internal/service/secretsmanager/secret_version.go index 57694b94950..6d20fa22c38 100644 --- a/internal/service/secretsmanager/secret_version.go +++ b/internal/service/secretsmanager/secret_version.go @@ -10,16 +10,15 @@ import ( "log" "strings" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" - "github.com/hashicorp/terraform-provider-aws/internal/flex" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) @@ -75,7 +74,7 @@ func ResourceSecretVersion() *schema.Resource { func resourceSecretVersionCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID := d.Get("secret_id").(string) input := &secretsmanager.PutSecretValueInput{ @@ -103,11 +102,16 @@ func resourceSecretVersionCreate(ctx context.Context, d *schema.ResourceData, me } if v, ok := d.GetOk("version_stages"); ok { - input.VersionStages = flex.ExpandStringSet(v.(*schema.Set)) + versionStagesSet := v.(*schema.Set) + versionStages := make([]string, 0, versionStagesSet.Len()) + for _, stage := range versionStagesSet.List() { + versionStages = append(versionStages, stage.(string)) + } + input.VersionStages = versionStages } log.Printf("[DEBUG] Putting Secrets Manager Secret %q value", secretID) - output, err := conn.PutSecretValueWithContext(ctx, input) + output, err := conn.PutSecretValue(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "putting Secrets Manager Secret value: %s", err) } @@ -119,7 +123,7 @@ func resourceSecretVersionCreate(ctx context.Context, d *schema.ResourceData, me func resourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID, versionID, err := DecodeSecretVersionID(d.Id()) if err != nil { @@ -136,13 +140,13 @@ func resourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { var err error - output, err = conn.GetSecretValueWithContext(ctx, input) + output, err = conn.GetSecretValue(ctx, input) - if d.IsNewResource() && tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if d.IsNewResource() && tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return retry.RetryableError(err) } - if d.IsNewResource() && tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { + if d.IsNewResource() && tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { return retry.RetryableError(err) } @@ -154,16 +158,16 @@ func resourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta }) if tfresource.TimedOut(err) { - output, err = conn.GetSecretValueWithContext(ctx, input) + output, err = conn.GetSecretValue(ctx, input) } - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { log.Printf("[WARN] Secrets Manager Secret Version (%s) not found, removing from state", d.Id()) d.SetId("") return diags } - if !d.IsNewResource() && tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { + if !d.IsNewResource() && tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { log.Printf("[WARN] Secrets Manager Secret Version (%s) not found, removing from state", d.Id()) d.SetId("") return diags @@ -183,7 +187,7 @@ func resourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta d.Set("version_id", output.VersionId) d.Set("arn", output.ARN) - if err := d.Set("version_stages", flex.FlattenStringList(output.VersionStages)); err != nil { + if err := d.Set("version_stages", output.VersionStages); err != nil { return sdkdiag.AppendErrorf(diags, "setting version_stages: %s", err) } @@ -192,7 +196,7 @@ func resourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID, versionID, err := DecodeSecretVersionID(d.Id()) if err != nil { @@ -213,7 +217,7 @@ func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, me } log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %s", input) - _, err := conn.UpdateSecretVersionStageWithContext(ctx, input) + _, err := conn.UpdateSecretVersionStage(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) } @@ -231,7 +235,7 @@ func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, me VersionStage: aws.String(stage.(string)), } log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %s", input) - _, err := conn.UpdateSecretVersionStageWithContext(ctx, input) + _, err := conn.UpdateSecretVersionStage(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) } @@ -242,7 +246,7 @@ func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, me func resourceSecretVersionDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID, versionID, err := DecodeSecretVersionID(d.Id()) if err != nil { @@ -262,12 +266,12 @@ func resourceSecretVersionDelete(ctx context.Context, d *schema.ResourceData, me VersionStage: aws.String(stage.(string)), } log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %s", input) - _, err := conn.UpdateSecretVersionStageWithContext(ctx, input) + _, err := conn.UpdateSecretVersionStage(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return diags } - if tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { + if tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { return diags } return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) diff --git a/internal/service/secretsmanager/secret_version_data_source.go b/internal/service/secretsmanager/secret_version_data_source.go index 4228b6b4d76..f5391fcc5b8 100644 --- a/internal/service/secretsmanager/secret_version_data_source.go +++ b/internal/service/secretsmanager/secret_version_data_source.go @@ -8,14 +8,13 @@ import ( "fmt" "log" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" - "github.com/hashicorp/terraform-provider-aws/internal/flex" ) // @SDKDataSource("aws_secretsmanager_secret_version") @@ -63,7 +62,7 @@ func DataSourceSecretVersion() *schema.Resource { func dataSourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID := d.Get("secret_id").(string) var version string @@ -82,12 +81,12 @@ func dataSourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, me } log.Printf("[DEBUG] Reading Secrets Manager Secret Version: %s", input) - output, err := conn.GetSecretValueWithContext(ctx, input) + output, err := conn.GetSecretValue(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q Version %q not found", secretID, version) } - if tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { + if tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q Version %q not found", secretID, version) } return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Version: %s", err) @@ -100,7 +99,7 @@ func dataSourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, me d.Set("secret_binary", string(output.SecretBinary)) d.Set("arn", output.ARN) - if err := d.Set("version_stages", flex.FlattenStringList(output.VersionStages)); err != nil { + if err := d.Set("version_stages", output.VersionStages); err != nil { return sdkdiag.AppendErrorf(diags, "setting version_stages: %s", err) } diff --git a/internal/service/secretsmanager/secret_version_data_source_test.go b/internal/service/secretsmanager/secret_version_data_source_test.go index b7af6627d96..c5d9f3b70ee 100644 --- a/internal/service/secretsmanager/secret_version_data_source_test.go +++ b/internal/service/secretsmanager/secret_version_data_source_test.go @@ -8,11 +8,11 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/secretsmanager" 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/names" ) func TestAccSecretsManagerSecretVersionDataSource_basic(t *testing.T) { @@ -23,7 +23,7 @@ func TestAccSecretsManagerSecretVersionDataSource_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { @@ -48,7 +48,7 @@ func TestAccSecretsManagerSecretVersionDataSource_versionID(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { @@ -69,7 +69,7 @@ func TestAccSecretsManagerSecretVersionDataSource_versionStage(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { diff --git a/internal/service/secretsmanager/secret_version_test.go b/internal/service/secretsmanager/secret_version_test.go index 4c9fc8c0bf6..843250ae0f2 100644 --- a/internal/service/secretsmanager/secret_version_test.go +++ b/internal/service/secretsmanager/secret_version_test.go @@ -8,16 +8,18 @@ import ( "fmt" "testing" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" 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" tfsecretsmanager "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" + tfsm "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" "github.com/hashicorp/terraform-provider-aws/internal/verify" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccSecretsManagerSecretVersion_basicString(t *testing.T) { @@ -29,7 +31,7 @@ func TestAccSecretsManagerSecretVersion_basicString(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretVersionDestroy(ctx), Steps: []resource.TestStep{ @@ -62,7 +64,7 @@ func TestAccSecretsManagerSecretVersion_base64Binary(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretVersionDestroy(ctx), Steps: []resource.TestStep{ @@ -94,7 +96,7 @@ func TestAccSecretsManagerSecretVersion_versionStages(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretVersionDestroy(ctx), Steps: []resource.TestStep{ @@ -140,7 +142,7 @@ func TestAccSecretsManagerSecretVersion_versionStages(t *testing.T) { func testAccCheckSecretVersionDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_secretsmanager_secret_version" { @@ -157,13 +159,13 @@ func testAccCheckSecretVersionDestroy(ctx context.Context) resource.TestCheckFun VersionId: aws.String(versionID), } - output, err := conn.GetSecretValueWithContext(ctx, input) + output, err := conn.GetSecretValue(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, tfsm.ErrCodeResourceNotFoundException) { return nil } - if tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "was deleted") || tfawserr.ErrMessageContains(err, secretsmanager.ErrCodeInvalidRequestException, "was marked for deletion") { + if tfawserr.ErrMessageContains(err, tfsm.ErrCodeInvalidRequestException, "was deleted") || tfawserr.ErrMessageContains(err, tfsm.ErrCodeInvalidRequestException, "was marked for deletion") { return nil } return err @@ -177,7 +179,7 @@ func testAccCheckSecretVersionDestroy(ctx context.Context) resource.TestCheckFun return nil } - if len(output.VersionStages) == 1 && aws.StringValue(output.VersionStages[0]) == "AWSCURRENT" { + if len(output.VersionStages) == 1 && output.VersionStages[0] == "AWSCURRENT" { return nil } @@ -200,14 +202,14 @@ func testAccCheckSecretVersionExists(ctx context.Context, resourceName string, v return err } - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) input := &secretsmanager.GetSecretValueInput{ SecretId: aws.String(secretID), VersionId: aws.String(versionID), } - output, err := conn.GetSecretValueWithContext(ctx, input) + output, err := conn.GetSecretValue(ctx, input) if err != nil { return err diff --git a/internal/service/secretsmanager/secrets_data_source.go b/internal/service/secretsmanager/secrets_data_source.go index e33af97f5ed..faf939a6eb8 100644 --- a/internal/service/secretsmanager/secrets_data_source.go +++ b/internal/service/secretsmanager/secrets_data_source.go @@ -6,8 +6,9 @@ package secretsmanager import ( "context" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" @@ -37,7 +38,7 @@ func DataSourceSecrets() *schema.Resource { func dataSourceSecretsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).SecretsManagerConn(ctx) + conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) input := &secretsmanager.ListSecretsInput{} @@ -45,26 +46,18 @@ func dataSourceSecretsRead(ctx context.Context, d *schema.ResourceData, meta int input.Filters = namevaluesfilters.New(v.(*schema.Set)).SecretsmanagerFilters() } - var results []*secretsmanager.SecretListEntry + var results []types.SecretListEntry - err := conn.ListSecretsPagesWithContext(ctx, input, func(page *secretsmanager.ListSecretsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + paginator := secretsmanager.NewListSecretsPaginator(conn, input) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + return sdkdiag.AppendErrorf(diags, "listing Secrets Manager Secrets: %s", err) } - for _, secretListEntry := range page.SecretList { - if secretListEntry == nil { - continue - } - - results = append(results, secretListEntry) + if page != nil { + results = append(results, page.SecretList...) } - - return !lastPage - }) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "listing Secrets Manager Secrets: %s", err) } var arns, names []string diff --git a/internal/service/secretsmanager/secrets_data_source_test.go b/internal/service/secretsmanager/secrets_data_source_test.go index a247c79e653..850591d7546 100644 --- a/internal/service/secretsmanager/secrets_data_source_test.go +++ b/internal/service/secretsmanager/secrets_data_source_test.go @@ -9,11 +9,11 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/service/secretsmanager" 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/names" ) func TestAccSecretsManagerSecretsDataSource_filter(t *testing.T) { @@ -32,7 +32,7 @@ func TestAccSecretsManagerSecretsDataSource_filter(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, secretsmanager.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index 93068a3ee7b..bf89ab48594 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -5,9 +5,8 @@ package secretsmanager import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - secretsmanager_sdkv1 "github.com/aws/aws-sdk-go/service/secretsmanager" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + secretsmanager_sdkv2 "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -77,11 +76,15 @@ func (p *servicePackage) ServicePackageName() string { return names.SecretsManager } -// NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*secretsmanager_sdkv1.SecretsManager, error) { - sess := config["session"].(*session_sdkv1.Session) +// NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*secretsmanager_sdkv2.Client, error) { + cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return secretsmanager_sdkv1.New(sess.Copy(&aws_sdkv1.Config{Endpoint: aws_sdkv1.String(config["endpoint"].(string))})), nil + return secretsmanager_sdkv2.NewFromConfig(cfg, func(o *secretsmanager_sdkv2.Options) { + if endpoint := config["endpoint"].(string); endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + }), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/secretsmanager/sweep.go b/internal/service/secretsmanager/sweep.go index d81e8541513..9393ef8097f 100644 --- a/internal/service/secretsmanager/sweep.go +++ b/internal/service/secretsmanager/sweep.go @@ -7,12 +7,12 @@ import ( "fmt" "log" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" - "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv1" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" ) func RegisterSweepers() { @@ -33,40 +33,43 @@ func sweepSecretPolicies(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.SecretsManagerConn(ctx) - - err = conn.ListSecretsPagesWithContext(ctx, &secretsmanager.ListSecretsInput{}, func(page *secretsmanager.ListSecretsOutput, lastPage bool) bool { - if len(page.SecretList) == 0 { - log.Print("[DEBUG] No Secrets Manager Secrets to sweep") - return true + conn := client.SecretsManagerClient(ctx) + + paginator := secretsmanager.NewListSecretsPaginator(conn, &secretsmanager.ListSecretsInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Secrets Manager Secret sweep for %s: %s", region, err) + return nil + } + return fmt.Errorf("error retrieving Secrets Manager Secrets: %w", err) } - for _, secret := range page.SecretList { - name := aws.StringValue(secret.Name) - - log.Printf("[INFO] Deleting Secrets Manager Secret Policy: %s", name) - input := &secretsmanager.DeleteResourcePolicyInput{ - SecretId: aws.String(name), + if page != nil { + if len(page.SecretList) == 0 { + log.Print("[DEBUG] No Secrets Manager Secrets to sweep") } - _, err := conn.DeleteResourcePolicyWithContext(ctx, input) - if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { - continue + for _, secret := range page.SecretList { + name := aws.StringValue(secret.Name) + + log.Printf("[INFO] Deleting Secrets Manager Secret Policy: %s", name) + input := &secretsmanager.DeleteResourcePolicyInput{ + SecretId: aws.String(name), } - log.Printf("[ERROR] Failed to delete Secrets Manager Secret Policy (%s): %s", name, err) - } - } - return !lastPage - }) - if err != nil { - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Secrets Manager Secret sweep for %s: %s", region, err) - return nil + _, err := conn.DeleteResourcePolicy(ctx, input) + if err != nil { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { + continue + } + log.Printf("[ERROR] Failed to delete Secrets Manager Secret Policy (%s): %s", name, err) + } + } } - return fmt.Errorf("Error retrieving Secrets Manager Secrets: %w", err) } + return nil } @@ -76,40 +79,42 @@ func sweepSecrets(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.SecretsManagerConn(ctx) - - err = conn.ListSecretsPagesWithContext(ctx, &secretsmanager.ListSecretsInput{}, func(page *secretsmanager.ListSecretsOutput, lastPage bool) bool { - if len(page.SecretList) == 0 { - log.Print("[DEBUG] No Secrets Manager Secrets to sweep") - return true + conn := client.SecretsManagerClient(ctx) + + paginator := secretsmanager.NewListSecretsPaginator(conn, &secretsmanager.ListSecretsInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ctx) + if err != nil { + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Secrets Manager Secret sweep for %s: %s", region, err) + return nil + } + return fmt.Errorf("error retrieving Secrets Manager Secrets: %w", err) } - for _, secret := range page.SecretList { - name := aws.StringValue(secret.Name) - - log.Printf("[INFO] Deleting Secrets Manager Secret: %s", name) - input := &secretsmanager.DeleteSecretInput{ - ForceDeleteWithoutRecovery: aws.Bool(true), - SecretId: aws.String(name), + if page != nil { + if len(page.SecretList) == 0 { + log.Print("[DEBUG] No Secrets Manager Secrets to sweep") } - _, err := conn.DeleteSecretWithContext(ctx, input) - if err != nil { - if tfawserr.ErrCodeEquals(err, secretsmanager.ErrCodeResourceNotFoundException) { - continue + for _, secret := range page.SecretList { + name := aws.StringValue(secret.Name) + + log.Printf("[INFO] Deleting Secrets Manager Secret: %s", name) + input := &secretsmanager.DeleteSecretInput{ + ForceDeleteWithoutRecovery: aws.Bool(true), + SecretId: aws.String(name), } - log.Printf("[ERROR] Failed to delete Secrets Manager Secret (%s): %s", name, err) - } - } - return !lastPage - }) - if err != nil { - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Secrets Manager Secret sweep for %s: %s", region, err) - return nil + _, err := conn.DeleteSecret(ctx, input) + if err != nil { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { + continue + } + log.Printf("[ERROR] Failed to delete Secrets Manager Secret (%s): %s", name, err) + } + } } - return fmt.Errorf("Error retrieving Secrets Manager Secrets: %s", err) } return nil } diff --git a/internal/service/secretsmanager/tags_gen.go b/internal/service/secretsmanager/tags_gen.go index 5ebd56f1245..e38ebe4176d 100644 --- a/internal/service/secretsmanager/tags_gen.go +++ b/internal/service/secretsmanager/tags_gen.go @@ -5,9 +5,9 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" + awstypes "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/logging" @@ -19,11 +19,11 @@ import ( // []*SERVICE.Tag handling // Tags returns secretsmanager service tags. -func Tags(tags tftags.KeyValueTags) []*secretsmanager.Tag { - result := make([]*secretsmanager.Tag, 0, len(tags)) +func Tags(tags tftags.KeyValueTags) []awstypes.Tag { + result := make([]awstypes.Tag, 0, len(tags)) for k, v := range tags.Map() { - tag := &secretsmanager.Tag{ + tag := awstypes.Tag{ Key: aws.String(k), Value: aws.String(v), } @@ -35,11 +35,11 @@ func Tags(tags tftags.KeyValueTags) []*secretsmanager.Tag { } // KeyValueTags creates tftags.KeyValueTags from secretsmanager service tags. -func KeyValueTags(ctx context.Context, tags []*secretsmanager.Tag) tftags.KeyValueTags { +func KeyValueTags(ctx context.Context, tags []awstypes.Tag) tftags.KeyValueTags { m := make(map[string]*string, len(tags)) for _, tag := range tags { - m[aws.StringValue(tag.Key)] = tag.Value + m[aws.ToString(tag.Key)] = tag.Value } return tftags.New(ctx, m) @@ -47,7 +47,7 @@ func KeyValueTags(ctx context.Context, tags []*secretsmanager.Tag) tftags.KeyVal // getTagsIn returns secretsmanager service tags from Context. // nil is returned if there are no input tags. -func getTagsIn(ctx context.Context) []*secretsmanager.Tag { +func getTagsIn(ctx context.Context) []awstypes.Tag { if inContext, ok := tftags.FromContext(ctx); ok { if tags := Tags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { return tags @@ -58,7 +58,7 @@ func getTagsIn(ctx context.Context) []*secretsmanager.Tag { } // setTagsOut sets secretsmanager service tags in Context. -func setTagsOut(ctx context.Context, tags []*secretsmanager.Tag) { +func setTagsOut(ctx context.Context, tags []awstypes.Tag) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = option.Some(KeyValueTags(ctx, tags)) } @@ -67,7 +67,7 @@ func setTagsOut(ctx context.Context, tags []*secretsmanager.Tag) { // updateTags updates secretsmanager service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func updateTags(ctx context.Context, conn secretsmanageriface.SecretsManagerAPI, identifier string, oldTagsMap, newTagsMap any) error { +func updateTags(ctx context.Context, conn *secretsmanager.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*secretsmanager.Options)) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -78,10 +78,10 @@ func updateTags(ctx context.Context, conn secretsmanageriface.SecretsManagerAPI, if len(removedTags) > 0 { input := &secretsmanager.UntagResourceInput{ SecretId: aws.String(identifier), - TagKeys: aws.StringSlice(removedTags.Keys()), + TagKeys: removedTags.Keys(), } - _, err := conn.UntagResourceWithContext(ctx, input) + _, err := conn.UntagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("untagging resource (%s): %w", identifier, err) @@ -96,7 +96,7 @@ func updateTags(ctx context.Context, conn secretsmanageriface.SecretsManagerAPI, Tags: Tags(updatedTags), } - _, err := conn.TagResourceWithContext(ctx, input) + _, err := conn.TagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("tagging resource (%s): %w", identifier, err) @@ -109,5 +109,5 @@ func updateTags(ctx context.Context, conn secretsmanageriface.SecretsManagerAPI, // UpdateTags updates secretsmanager service tags. // It is called from outside this package. func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { - return updateTags(ctx, meta.(*conns.AWSClient).SecretsManagerConn(ctx), identifier, oldTags, newTags) + return updateTags(ctx, meta.(*conns.AWSClient).SecretsManagerClient(ctx), identifier, oldTags, newTags) } diff --git a/names/data/names_data.csv b/names/data/names_data.csv index f7a00f2795f..4cb5e439a63 100644 --- a/names/data/names_data.csv +++ b/names/data/names_data.csv @@ -321,7 +321,7 @@ savingsplans,savingsplans,savingsplans,savingsplans,,savingsplans,,,SavingsPlans ,,,,,,,,,,,,,,,,,Schema Conversion Tool,AWS,x,,,,,,No SDK support sdb,sdb,simpledb,,simpledb,sdb,,sdb,SimpleDB,SimpleDB,,1,,aws_simpledb_,aws_sdb_,,simpledb_,SDB (SimpleDB),Amazon,,,,,,, scheduler,scheduler,scheduler,scheduler,,scheduler,,,Scheduler,Scheduler,,,2,,aws_scheduler_,,scheduler_,EventBridge Scheduler,Amazon,,,,,,, -secretsmanager,secretsmanager,secretsmanager,secretsmanager,,secretsmanager,,,SecretsManager,SecretsManager,,1,,,aws_secretsmanager_,,secretsmanager_,Secrets Manager,AWS,,,,,,, +secretsmanager,secretsmanager,secretsmanager,secretsmanager,,secretsmanager,,,SecretsManager,SecretsManager,,,2,,aws_secretsmanager_,,secretsmanager_,Secrets Manager,AWS,,,,,,, securityhub,securityhub,securityhub,securityhub,,securityhub,,,SecurityHub,SecurityHub,,,2,,aws_securityhub_,,securityhub_,Security Hub,AWS,,,,,,, securitylake,securitylake,securitylake,securitylake,,securitylake,,,SecurityLake,SecurityLake,,,2,,aws_securitylake_,,securitylake_,Security Lake,Amazon,,,,,,, serverlessrepo,serverlessrepo,serverlessapplicationrepository,serverlessapplicationrepository,,serverlessrepo,,serverlessapprepo;serverlessapplicationrepository,ServerlessRepo,ServerlessApplicationRepository,,1,,aws_serverlessapplicationrepository_,aws_serverlessrepo_,,serverlessapplicationrepository_,Serverless Application Repository,AWS,,,,,,, diff --git a/names/names.go b/names/names.go index 021a881c70a..bf6c2422f17 100644 --- a/names/names.go +++ b/names/names.go @@ -81,6 +81,7 @@ const ( RolesAnywhereEndpointID = "rolesanywhere" Route53DomainsEndpointID = "route53domains" SchedulerEndpointID = "scheduler" + SecretsManagerEndpointID = "secretsmanager" SecurityLakeEndpointID = "securitylake" ServiceQuotasEndpointID = "servicequotas" S3EndpointID = "s3" From aa414946fcae042fb5839fe276859a51ba365633 Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Sun, 7 Jan 2024 21:01:52 +0100 Subject: [PATCH 11/35] split namevaluesfilters for v2 to new version --- .../generators/servicefilters/main.go | 1 - .../namevaluesfilters/service_filters_gen.go | 23 --- .../service_generation_customizations.go | 6 +- .../generate/namevaluesfiltersv2/README.md | 24 +++ .../generators/servicefilters/README.md | 42 ++++ .../generators/servicefilters/main.go | 132 +++++++++++++ .../name_values_filters.go | 128 ++++++++++++ .../name_values_filters_test.go | 184 ++++++++++++++++++ .../service_filters_gen.go | 31 +++ .../service_generation_customizations.go | 48 +++++ .../secretsmanager/secrets_data_source.go | 6 +- 11 files changed, 593 insertions(+), 32 deletions(-) create mode 100644 internal/generate/namevaluesfiltersv2/README.md create mode 100644 internal/generate/namevaluesfiltersv2/generators/servicefilters/README.md create mode 100644 internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go create mode 100644 internal/generate/namevaluesfiltersv2/name_values_filters.go create mode 100644 internal/generate/namevaluesfiltersv2/name_values_filters_test.go create mode 100644 internal/generate/namevaluesfiltersv2/service_filters_gen.go create mode 100644 internal/generate/namevaluesfiltersv2/service_generation_customizations.go diff --git a/internal/generate/namevaluesfilters/generators/servicefilters/main.go b/internal/generate/namevaluesfilters/generators/servicefilters/main.go index 05ae86ee889..97ffc27a602 100644 --- a/internal/generate/namevaluesfilters/generators/servicefilters/main.go +++ b/internal/generate/namevaluesfilters/generators/servicefilters/main.go @@ -32,7 +32,6 @@ var sliceServiceNames = []string{ "rds", "resourcegroupstaggingapi", "route53resolver", - "secretsmanager", } type TemplateData struct { diff --git a/internal/generate/namevaluesfilters/service_filters_gen.go b/internal/generate/namevaluesfilters/service_filters_gen.go index 62a2b4a84c8..4332fa53eb7 100644 --- a/internal/generate/namevaluesfilters/service_filters_gen.go +++ b/internal/generate/namevaluesfilters/service_filters_gen.go @@ -17,7 +17,6 @@ import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" "github.com/aws/aws-sdk-go/service/route53resolver" - secretsmanagertypes "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" ) // []*SERVICE.Filter handling @@ -307,25 +306,3 @@ func (filters NameValuesFilters) Route53resolverFilters() []*route53resolver.Fil return result } - -// SecretsmanagerFilters returns secretsmanager service filters. -func (filters NameValuesFilters) SecretsmanagerFilters() []secretsmanagertypes.Filter { - m := filters.Map() - - if len(m) == 0 { - return nil - } - - result := make([]secretsmanagertypes.Filter, 0, len(m)) - - for k, v := range m { - filter := secretsmanagertypes.Filter{ - Key: secretsmanagertypes.FilterNameStringType(k), - Values: v, - } - - result = append(result, filter) - } - - return result -} diff --git a/internal/generate/namevaluesfilters/service_generation_customizations.go b/internal/generate/namevaluesfilters/service_generation_customizations.go index 0028d5e49fe..0f57d9385e2 100644 --- a/internal/generate/namevaluesfilters/service_generation_customizations.go +++ b/internal/generate/namevaluesfilters/service_generation_customizations.go @@ -5,15 +5,11 @@ package namevaluesfilters -import "fmt" - // ServiceFilterPackage determines the service filter type package. func ServiceFilterPackage(serviceName string) string { switch serviceName { - case "secretsmanager": - return fmt.Sprintf("github.com/aws/aws-sdk-go-v2/service/%s/types", serviceName) default: - return "github.com/aws/aws-sdk-go/service/" + serviceName + return serviceName } } diff --git a/internal/generate/namevaluesfiltersv2/README.md b/internal/generate/namevaluesfiltersv2/README.md new file mode 100644 index 00000000000..73e80758c4a --- /dev/null +++ b/internal/generate/namevaluesfiltersv2/README.md @@ -0,0 +1,24 @@ +# namevaluesfiltersv2 + +The `namevaluesfiltersv2` package is designed to provide a consistent interface for handling AWS resource filtering for AWS SDK for Go v2. + +This package implements a single `NameValuesFilters` type, which covers all filter handling logic, such as merging filters, via functions on the single type. The underlying implementation is compatible with Go operations such as `len()`. + +Full documentation for this package can be found on [GoDoc](https://godoc.org/github.com/hashicorp/terraform-provider-aws/internal/generate/namevaluesfiltersv2). + +Many AWS Go SDK v2 services that support resource filtering have their service-specific Go type conversion functions to and from `NameValuesFilters` code generated. Converting from `NameValuesFilters` to AWS Go SDK v2 types is done via `{SERVICE}Filters()` functions on the type. For more information about this code generation, see the [`generators/servicefilters` README](generators/servicefilters/README.md). + +Any filtering functions that cannot be generated should be hand implemented in a service-specific source file and follow the format of similar generated code wherever possible. The first line of the source file should be `// +build !generate`. This prevents the file's inclusion during the code generation phase. + +## Code Structure + +```text +internal/generate/namevaluesfiltersv2 +├── generators +│ └── servicefilters (generates service_filters_gen.go) +├── name_values_filters_test.go (unit tests for core logic) +├── name_values_filters.go (core logic) +├── service_generation_customizations.go (shared AWS Go SDK service customizations for generators) +├── service_filters_gen.go (generated AWS Go SDK service conversion functions) +└── _filters.go (any service-specific functions that cannot be generated) +``` diff --git a/internal/generate/namevaluesfiltersv2/generators/servicefilters/README.md b/internal/generate/namevaluesfiltersv2/generators/servicefilters/README.md new file mode 100644 index 00000000000..e86cf2585a0 --- /dev/null +++ b/internal/generate/namevaluesfiltersv2/generators/servicefilters/README.md @@ -0,0 +1,42 @@ +# servicefilters + +This package contains a code generator to consistently handle the various AWS Go SDK service implementations for converting service filter types to/from `NameValuesFilters`. Not all AWS Go SDK services that support filters are generated in this manner. + +To run this code generator, execute `go generate ./...` from the root of the repository. The general workflow for the generator is: + +- Generate Go file contents via template from local variables and functions +- Go format file contents +- Write file contents to `service_filters_gen.go` file + +## Example Output + +```go +// DocDBFilters returns docdb service filters. +func (filters NameValuesFilters) DocDBFilters() []*docdb.Filter { + m := filters.Map() + + if len(m) == 0 { + return nil + } + + result := make([]*docdb.Filter, 0, len(m)) + + for k, v := range m { + filter := &docdb.Filter{ + Name: aws.String(k), + Values: aws.StringSlice(v), + } + + result = append(result, filter) + } + + return result +} +``` + +## Implementing a New Generated Service + +- In `main.go`: Add service name, e.g. `docdb`, to one of the implementation handlers + - Use `sliceServiceNames` if the AWS Go SDK service implements a specific Go type such as `Filter` +- Run `go generate ./...` (or `make gen`) from the root of the repository to regenerate the code +- Run `go test ./...` (or `make test`) from the root of the repository to ensure the generated code compiles diff --git a/internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go b/internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go new file mode 100644 index 00000000000..661d6689338 --- /dev/null +++ b/internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go @@ -0,0 +1,132 @@ +//go:build generate +// +build generate + +package main + +import ( + "bytes" + "go/format" + "log" + "os" + "sort" + "strings" + "text/template" + + "github.com/hashicorp/terraform-provider-aws/internal/generate/namevaluesfiltersv2" +) + +const filename = `service_filters_v2_gen.go` + +// Representing types such as []*ec2.Filter, []*rds.Filter, ... +var sliceServiceNames = []string{ + "secretsmanager", +} + +type TemplateData struct { + SliceServiceNames []string +} + +func main() { + // Always sort to reduce any potential generation churn + sort.Strings(sliceServiceNames) + + templateData := TemplateData{ + SliceServiceNames: sliceServiceNames, + } + templateFuncMap := template.FuncMap{ + "FilterPackage": namevaluesfiltersv2.ServiceFilterPackage, + "FilterPackagePrefix": namevaluesfiltersv2.ServiceFilterPackagePrefix, + "FilterType": namevaluesfiltersv2.ServiceFilterType, + "FilterTypeNameField": namevaluesfiltersv2.ServiceFilterTypeNameField, + "FilterTypeValuesField": namevaluesfiltersv2.ServiceFilterTypeValuesField, + "Title": strings.Title, + } + + tmpl, err := template.New("servicefilters").Funcs(templateFuncMap).Parse(templateBody) + + if err != nil { + log.Fatalf("error parsing template: %s", err) + } + + var buffer bytes.Buffer + err = tmpl.Execute(&buffer, templateData) + + if err != nil { + log.Fatalf("error executing template: %s", err) + } + + generatedFileContents, err := format.Source(buffer.Bytes()) + + if err != nil { + log.Fatalf("error formatting generated file: %s", err) + } + + f, err := os.Create(filename) + + if err != nil { + log.Fatalf("error creating file (%s): %s", filename, err) + } + + defer f.Close() + + _, err = f.Write(generatedFileContents) + + if err != nil { + log.Fatalf("error writing to file (%s): %s", filename, err) + } +} + +var templateBody = ` +// Code generated by generators/servicefilters/main.go; DO NOT EDIT. + +package namevaluesfiltersv2 + +import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports +{{- range .SliceServiceNames }} +{{- if eq . (. | FilterPackage) }} + {{ . }} +{{- end }} +{{- end }} +) + +// []*SERVICE.Filter handling +{{- range .SliceServiceNames }} + +// {{ . | Title }}Filters returns {{ . }} service filters. +func (filters NameValuesFilters) {{ . | Title }}Filters() []*{{ . | FilterPackagePrefix }}.{{ . | FilterType }} { + m := filters.Map() + + if len(m) == 0 { + return nil + } + + result := make([]{{ . | FilterPackagePrefix }}.{{ . | FilterType }}, 0, len(m)) + + for k, v := range m { + filter := {{ . | FilterPackagePrefix }}.{{ . | FilterType }}{ + {{ . | FilterTypeNameField }}: { . | FilterPackagePrefix }}.FilterNameStringType(k), + {{ . | FilterTypeValuesField }}: v, + } + + result = append(result, filter) + } + + return result +} +{{- end }} +` + + + result := make([]secretsmanagertypes.Filter, 0, len(m)) + + for k, v := range m { + filter := secretsmanagertypes.Filter{ + Key: secretsmanagertypes.FilterNameStringType(k), + Values: v, + } + + result = append(result, filter) + } + + return result +} diff --git a/internal/generate/namevaluesfiltersv2/name_values_filters.go b/internal/generate/namevaluesfiltersv2/name_values_filters.go new file mode 100644 index 00000000000..2bba6c56ced --- /dev/null +++ b/internal/generate/namevaluesfiltersv2/name_values_filters.go @@ -0,0 +1,128 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package namevaluesfiltersv2 + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +// NameValuesFilters is a standard implementation for AWS resource filters. +// The AWS Go SDK is split into multiple service packages, each service with +// its own Go struct type representing a resource filter. To standardize logic +// across all these Go types, we convert them into this Go type. +type NameValuesFilters map[string][]string + +// Add adds missing and updates existing filters from common Terraform Provider SDK types. +// Supports map[string]string, map[string][]string, *schema.Set. +func (filters NameValuesFilters) Add(i interface{}) NameValuesFilters { + switch value := i.(type) { + case map[string]string: + for name, v := range value { + if values, ok := filters[name]; ok { + filters[name] = append(values, v) + } else { + values = []string{v} + filters[name] = values + } + } + + case map[string][]string: + // We can't use fallthrough here, so recurse. + return filters.Add(NameValuesFilters(value)) + + case NameValuesFilters: + for name, vs := range value { + if values, ok := filters[name]; ok { + filters[name] = append(values, vs...) + } else { + values = make([]string, len(vs)) + copy(values, vs) + filters[name] = values + } + } + + case *schema.Set: + // The set of filters described by Schema(). + for _, filter := range value.List() { + m := filter.(map[string]interface{}) + name := m["name"].(string) + + for _, v := range m["values"].(*schema.Set).List() { + if values, ok := filters[name]; ok { + filters[name] = append(values, v.(string)) + } else { + values = []string{v.(string)} + filters[name] = values + } + } + } + } + + return filters +} + +// Map returns filter names mapped to their values. +// Duplicate values are eliminated and empty values removed. +func (filters NameValuesFilters) Map() map[string][]string { + result := make(map[string][]string) + + for k, v := range filters { + targetValues := make([]string, 0) + + SOURCE_VALUES: + for _, sourceValue := range v { + if sourceValue == "" { + continue + } + + for _, targetValue := range targetValues { + if sourceValue == targetValue { + continue SOURCE_VALUES + } + } + + targetValues = append(targetValues, sourceValue) + } + + if len(targetValues) == 0 { + continue + } + + result[k] = targetValues + } + + return result +} + +// New creates NameValuesFilters from common Terraform Provider SDK types. +// Supports map[string]string, map[string][]string, *schema.Set. +func New(i interface{}) NameValuesFilters { + return make(NameValuesFilters).Add(i) +} + +// Schema returns a *schema.Schema that represents a set of custom filtering criteria +// that a user can specify as input to a data source. +// It is conventional for an attribute of this type to be included as a top-level attribute called "filter". +func Schema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "values": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + } +} diff --git a/internal/generate/namevaluesfiltersv2/name_values_filters_test.go b/internal/generate/namevaluesfiltersv2/name_values_filters_test.go new file mode 100644 index 00000000000..5e98ab0ba72 --- /dev/null +++ b/internal/generate/namevaluesfiltersv2/name_values_filters_test.go @@ -0,0 +1,184 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package namevaluesfiltersv2_test + +import ( + "reflect" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/generate/namevaluesfilters" +) + +func TestNameValuesFiltersMap(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + filters namevaluesfilters.NameValuesFilters + want map[string][]string + }{ + { + name: "empty", + filters: namevaluesfilters.New(map[string][]string{}), + want: map[string][]string{}, + }, + { + name: "empty_strings", + filters: namevaluesfilters.New(map[string][]string{ + "name1": {""}, + "name2": {"", ""}, + }), + want: map[string][]string{}, + }, + { + name: "duplicates", + filters: namevaluesfilters.New(map[string][]string{ + "name1": {"value1"}, + "name2": {"value2a", "value2b", "", "value2a", "value2c", "value2c"}, + }), + want: map[string][]string{ + "name1": {"value1"}, + "name2": {"value2a", "value2b", "value2c"}, + }, + }, + } + + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + got := testCase.filters.Map() + + testNameValuesFiltersVerifyMap(t, got, testCase.want) + }) + } +} + +func TestNameValuesFiltersAdd(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + filters namevaluesfilters.NameValuesFilters + add interface{} + want map[string][]string + }{ + { + name: "empty", + filters: namevaluesfilters.New(map[string][]string{}), + add: nil, + want: map[string][]string{}, + }, + { + name: "add_all", + filters: namevaluesfilters.New(map[string]string{ + "name1": "value1", + "name2": "value2", + "name3": "value3", + }), + add: namevaluesfilters.New(map[string][]string{ + "name4": {"value4a", "value4b"}, + "name5": {"value5"}, + "name6": {"value6a", "value6b", "value6c"}, + }), + want: map[string][]string{ + "name1": {"value1"}, + "name2": {"value2"}, + "name3": {"value3"}, + "name4": {"value4a", "value4b"}, + "name5": {"value5"}, + "name6": {"value6a", "value6b", "value6c"}, + }, + }, + { + name: "mixed", + filters: namevaluesfilters.New(map[string][]string{ + "name1": {"value1a"}, + "name2": {"value2a", "value2b"}, + }), + add: map[string]string{ + "name1": "value1b", + "name3": "value3", + }, + want: map[string][]string{ + "name1": {"value1a", "value1b"}, + "name2": {"value2a", "value2b"}, + "name3": {"value3"}, + }, + }, + { + name: "from_set", + filters: namevaluesfilters.New(schema.NewSet(testNameValuesFiltersHashSet, []interface{}{ + map[string]interface{}{ + "name": "name1", + "values": schema.NewSet(schema.HashString, []interface{}{ + "value1", + }), + }, + map[string]interface{}{ + "name": "name2", + "values": schema.NewSet(schema.HashString, []interface{}{ + "value2a", + "value2b", + }), + }, + map[string]interface{}{ + "name": "name3", + "values": schema.NewSet(schema.HashString, []interface{}{ + "value3", + }), + }, + })), + add: map[string][]string{ + "name1": {"value1"}, + "name2": {"value2c"}, + }, + want: map[string][]string{ + "name1": {"value1"}, + "name2": {"value2a", "value2b", "value2c"}, + "name3": {"value3"}, + }, + }, + } + + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + got := testCase.filters.Add(testCase.add) + + testNameValuesFiltersVerifyMap(t, got.Map(), testCase.want) + }) + } +} + +func testNameValuesFiltersVerifyMap(t *testing.T, got map[string][]string, want map[string][]string) { + for k, wantV := range want { + gotV, ok := got[k] + + if !ok { + t.Errorf("want missing name: %s", k) + continue + } + + if !reflect.DeepEqual(gotV, wantV) { + t.Errorf("got name (%s) values %s; want values %s", k, gotV, wantV) + } + } + + for k := range got { + if _, ok := want[k]; !ok { + t.Errorf("got extra name: %s", k) + } + } +} + +func testNameValuesFiltersHashSet(v interface{}) int { + m := v.(map[string]interface{}) + return create.StringHashcode(m["name"].(string)) +} diff --git a/internal/generate/namevaluesfiltersv2/service_filters_gen.go b/internal/generate/namevaluesfiltersv2/service_filters_gen.go new file mode 100644 index 00000000000..e25053e6244 --- /dev/null +++ b/internal/generate/namevaluesfiltersv2/service_filters_gen.go @@ -0,0 +1,31 @@ +// Code generated by generators/servicefilters/main.go; DO NOT EDIT. + +package namevaluesfiltersv2 + +import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports + secretsmanagertypes "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" +) + +// []*SERVICE.Filter handling + +// SecretsmanagerFilters returns secretsmanager service filters. +func (filters NameValuesFilters) SecretsmanagerFilters() []secretsmanagertypes.Filter { + m := filters.Map() + + if len(m) == 0 { + return nil + } + + result := make([]secretsmanagertypes.Filter, 0, len(m)) + + for k, v := range m { + filter := secretsmanagertypes.Filter{ + Key: secretsmanagertypes.FilterNameStringType(k), + Values: v, + } + + result = append(result, filter) + } + + return result +} diff --git a/internal/generate/namevaluesfiltersv2/service_generation_customizations.go b/internal/generate/namevaluesfiltersv2/service_generation_customizations.go new file mode 100644 index 00000000000..31bbba1fce2 --- /dev/null +++ b/internal/generate/namevaluesfiltersv2/service_generation_customizations.go @@ -0,0 +1,48 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// This file contains code generation customizations for each AWS Go SDK service. + +package namevaluesfiltersv2 + +import "fmt" + +// ServiceFilterPackage determines the service filter type package. +func ServiceFilterPackage(serviceName string) string { + switch serviceName { + default: + return fmt.Sprintf("%[1]stypes \"github.com/aws/aws-sdk-go-v2/service/%[1]s/types\"", serviceName) + } +} + +// ServiceFilterPackage determines the service filter type package. +func ServiceFilterPackagePrefix(serviceName string) string { + switch serviceName { + default: + return fmt.Sprintf("%[1]stypes", serviceName) + } +} + +// ServiceFilterType determines the service filter type. +func ServiceFilterType(serviceName string) string { + switch serviceName { + default: + return "Filter" + } +} + +// ServiceFilterTypeNameField determines the service filter type name field. +func ServiceFilterTypeNameField(serviceName string) string { + switch serviceName { + default: + return "Key" + } +} + +// ServiceFilterTypeValuesField determines the service filter type values field. +func ServiceFilterTypeValuesField(serviceName string) string { + switch serviceName { + default: + return "Values" + } +} diff --git a/internal/service/secretsmanager/secrets_data_source.go b/internal/service/secretsmanager/secrets_data_source.go index faf939a6eb8..75c073dc040 100644 --- a/internal/service/secretsmanager/secrets_data_source.go +++ b/internal/service/secretsmanager/secrets_data_source.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" - "github.com/hashicorp/terraform-provider-aws/internal/generate/namevaluesfilters" + "github.com/hashicorp/terraform-provider-aws/internal/generate/namevaluesfiltersv2" ) // @SDKDataSource("aws_secretsmanager_secrets") @@ -26,7 +26,7 @@ func DataSourceSecrets() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - "filter": namevaluesfilters.Schema(), + "filter": namevaluesfiltersv2.Schema(), "names": { Type: schema.TypeSet, Computed: true, @@ -43,7 +43,7 @@ func dataSourceSecretsRead(ctx context.Context, d *schema.ResourceData, meta int input := &secretsmanager.ListSecretsInput{} if v, ok := d.GetOk("filter"); ok { - input.Filters = namevaluesfilters.New(v.(*schema.Set)).SecretsmanagerFilters() + input.Filters = namevaluesfiltersv2.New(v.(*schema.Set)).SecretsmanagerFilters() } var results []types.SecretListEntry From 3e6b738e6874a46ba977529b9fd58d0c065d3802 Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Sun, 7 Jan 2024 21:15:34 +0100 Subject: [PATCH 12/35] fix: providerlint --- internal/service/lambda/event_source_mapping_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/service/lambda/event_source_mapping_test.go b/internal/service/lambda/event_source_mapping_test.go index 31efbc020dc..b09448283f2 100644 --- a/internal/service/lambda/event_source_mapping_test.go +++ b/internal/service/lambda/event_source_mapping_test.go @@ -12,9 +12,9 @@ import ( "github.com/aws/aws-sdk-go-v2/service/kafka" "github.com/aws/aws-sdk-go-v2/service/mq" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/lambda" - "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" @@ -1242,11 +1242,11 @@ func testAccPreCheckMSK(ctx context.Context, t *testing.T) { } func testAccPreCheckSecretsManager(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) input := &secretsmanager.ListSecretsInput{} - _, err := conn.ListSecretsWithContext(ctx, input) + _, err := conn.ListSecrets(ctx, input) if acctest.PreCheckSkipError(err) { t.Skipf("skipping acceptance testing: %s", err) From 3e7978b26fb84aba2e658b33363d09adaff44699 Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Sun, 7 Jan 2024 21:40:36 +0100 Subject: [PATCH 13/35] fix: adapt log.Printf of to print object value --- internal/service/secretsmanager/secret.go | 10 +++++----- internal/service/secretsmanager/secret_data_source.go | 4 ++-- internal/service/secretsmanager/secret_version.go | 6 +++--- .../secretsmanager/secret_version_data_source.go | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/service/secretsmanager/secret.go b/internal/service/secretsmanager/secret.go index a53d2c9f009..06e96722408 100644 --- a/internal/service/secretsmanager/secret.go +++ b/internal/service/secretsmanager/secret.go @@ -160,7 +160,7 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte input.AddReplicaRegions = expandSecretReplicas(v.(*schema.Set).List()) } - log.Printf("[DEBUG] Creating Secrets Manager Secret: %s", input) + log.Printf("[DEBUG] Creating Secrets Manager Secret: %v", input) // Retry for secret recreation after deletion var output *secretsmanager.CreateSecretOutput @@ -326,7 +326,7 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte input.KmsKeyId = aws.String(v.(string)) } - log.Printf("[DEBUG] Updating Secrets Manager Secret: %s", input) + log.Printf("[DEBUG] Updating Secrets Manager Secret: %v", input) _, err := conn.UpdateSecret(ctx, input) if err != nil { @@ -346,7 +346,7 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte SecretId: aws.String(d.Id()), } - log.Printf("[DEBUG] Setting Secrets Manager Secret resource policy: %s", input) + log.Printf("[DEBUG] Setting Secrets Manager Secret resource policy: %v", input) _, err = tfresource.RetryWhenAWSErrMessageContains(ctx, PropagationTimeout, func() (interface{}, error) { return conn.PutResourcePolicy(ctx, input) @@ -439,7 +439,7 @@ func removeSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id s input.RemoveReplicaRegions = regions - log.Printf("[DEBUG] Removing Secrets Manager Secret Replicas: %s", input) + log.Printf("[DEBUG] Removing Secrets Manager Secret Replicas: %v", input) _, err := conn.RemoveRegionsFromReplication(ctx, input) @@ -465,7 +465,7 @@ func addSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id stri AddReplicaRegions: expandSecretReplicas(tfList), } - log.Printf("[DEBUG] Removing Secrets Manager Secret Replica: %s", input) + log.Printf("[DEBUG] Removing Secrets Manager Secret Replica: %v", input) _, err := conn.ReplicateSecretToRegions(ctx, input) diff --git a/internal/service/secretsmanager/secret_data_source.go b/internal/service/secretsmanager/secret_data_source.go index 5cdf3779b70..0ec9998cf88 100644 --- a/internal/service/secretsmanager/secret_data_source.go +++ b/internal/service/secretsmanager/secret_data_source.go @@ -80,7 +80,7 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, meta inte SecretId: aws.String(secretID), } - log.Printf("[DEBUG] Reading Secrets Manager Secret: %s", input) + log.Printf("[DEBUG] Reading Secrets Manager Secret: %v", input) output, err := conn.DescribeSecret(ctx, input) if err != nil { if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { @@ -103,7 +103,7 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, meta inte pIn := &secretsmanager.GetResourcePolicyInput{ SecretId: aws.String(d.Id()), } - log.Printf("[DEBUG] Reading Secrets Manager Secret policy: %s", pIn) + log.Printf("[DEBUG] Reading Secrets Manager Secret policy: %v", pIn) pOut, err := conn.GetResourcePolicy(ctx, pIn) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret policy: %s", err) diff --git a/internal/service/secretsmanager/secret_version.go b/internal/service/secretsmanager/secret_version.go index 6d20fa22c38..8e2d89ec83d 100644 --- a/internal/service/secretsmanager/secret_version.go +++ b/internal/service/secretsmanager/secret_version.go @@ -216,7 +216,7 @@ func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, me VersionStage: aws.String(stage.(string)), } - log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %s", input) + log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %v", input) _, err := conn.UpdateSecretVersionStage(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) @@ -234,7 +234,7 @@ func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, me SecretId: aws.String(secretID), VersionStage: aws.String(stage.(string)), } - log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %s", input) + log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %v", input) _, err := conn.UpdateSecretVersionStage(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) @@ -265,7 +265,7 @@ func resourceSecretVersionDelete(ctx context.Context, d *schema.ResourceData, me SecretId: aws.String(secretID), VersionStage: aws.String(stage.(string)), } - log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %s", input) + log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %v", input) _, err := conn.UpdateSecretVersionStage(ctx, input) if err != nil { if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { diff --git a/internal/service/secretsmanager/secret_version_data_source.go b/internal/service/secretsmanager/secret_version_data_source.go index f5391fcc5b8..783e44ac904 100644 --- a/internal/service/secretsmanager/secret_version_data_source.go +++ b/internal/service/secretsmanager/secret_version_data_source.go @@ -80,13 +80,13 @@ func dataSourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, me version = versionStage } - log.Printf("[DEBUG] Reading Secrets Manager Secret Version: %s", input) + log.Printf("[DEBUG] Reading Secrets Manager Secret Version: %v", input) output, err := conn.GetSecretValue(ctx, input) if err != nil { if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q Version %q not found", secretID, version) } - if tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { + if tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can't perform this operation on the secret because it was deleted") { return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q Version %q not found", secretID, version) } return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Version: %s", err) From b39ceaff279f785e6df58aeba1d37851b0e9cff6 Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Sun, 7 Jan 2024 22:13:46 +0100 Subject: [PATCH 14/35] revert: change to namevaluesfilters package --- .../namevaluesfilters/generators/servicefilters/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/generate/namevaluesfilters/generators/servicefilters/main.go b/internal/generate/namevaluesfilters/generators/servicefilters/main.go index 97ffc27a602..0846ad33710 100644 --- a/internal/generate/namevaluesfilters/generators/servicefilters/main.go +++ b/internal/generate/namevaluesfilters/generators/servicefilters/main.go @@ -96,7 +96,7 @@ import ( // nosemgrep:ci.semgrep.aws.multiple-service-imports "github.com/aws/aws-sdk-go/aws" {{- range .SliceServiceNames }} {{- if eq . (. | FilterPackage) }} - "{{ . }}" + "github.com/aws/aws-sdk-go/service/{{ . }}" {{- end }} {{- end }} ) From 21ea2e76a74bcaab4838702fee19dee5436cf230 Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Sun, 7 Jan 2024 22:18:39 +0100 Subject: [PATCH 15/35] fix: remove duplicate imports --- internal/service/secretsmanager/secret_policy_test.go | 7 +++---- internal/service/secretsmanager/secret_version_test.go | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/internal/service/secretsmanager/secret_policy_test.go b/internal/service/secretsmanager/secret_policy_test.go index c97463ebbb6..708b497f1da 100644 --- a/internal/service/secretsmanager/secret_policy_test.go +++ b/internal/service/secretsmanager/secret_policy_test.go @@ -19,7 +19,6 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfsecretsmanager "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" - tfsm "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -163,7 +162,7 @@ func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc output, err = conn.DescribeSecret(ctx, secretInput) } - if tfawserr.ErrCodeEquals(err, tfsm.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, tfsecretsmanager.ErrCodeResourceNotFoundException) { continue } @@ -181,8 +180,8 @@ func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc _, err = conn.GetResourcePolicy(ctx, input) - if tfawserr.ErrCodeEquals(err, tfsm.ErrCodeResourceNotFoundException) || - tfawserr.ErrMessageContains(err, tfsm.ErrCodeInvalidRequestException, + if tfawserr.ErrCodeEquals(err, tfsecretsmanager.ErrCodeResourceNotFoundException) || + tfawserr.ErrMessageContains(err, tfsecretsmanager.ErrCodeInvalidRequestException, "You can't perform this operation on the secret because it was marked for deletion.") { continue } diff --git a/internal/service/secretsmanager/secret_version_test.go b/internal/service/secretsmanager/secret_version_test.go index 843250ae0f2..b6c2b0fee92 100644 --- a/internal/service/secretsmanager/secret_version_test.go +++ b/internal/service/secretsmanager/secret_version_test.go @@ -17,7 +17,6 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfsecretsmanager "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" - tfsm "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -162,10 +161,10 @@ func testAccCheckSecretVersionDestroy(ctx context.Context) resource.TestCheckFun output, err := conn.GetSecretValue(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, tfsm.ErrCodeResourceNotFoundException) { + if tfawserr.ErrCodeEquals(err, tfsecretsmanager.ErrCodeResourceNotFoundException) { return nil } - if tfawserr.ErrMessageContains(err, tfsm.ErrCodeInvalidRequestException, "was deleted") || tfawserr.ErrMessageContains(err, tfsm.ErrCodeInvalidRequestException, "was marked for deletion") { + if tfawserr.ErrMessageContains(err, tfsecretsmanager.ErrCodeInvalidRequestException, "was deleted") || tfawserr.ErrMessageContains(err, tfsecretsmanager.ErrCodeInvalidRequestException, "was marked for deletion") { return nil } return err From 51afec381b1673351e909d964a575f66e0cc7f47 Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:52:22 +0100 Subject: [PATCH 16/35] fix: remove leftovers --- .../generators/servicefilters/main.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go b/internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go index 661d6689338..88368f5110d 100644 --- a/internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go +++ b/internal/generate/namevaluesfiltersv2/generators/servicefilters/main.go @@ -115,18 +115,3 @@ func (filters NameValuesFilters) {{ . | Title }}Filters() []*{{ . | FilterPackag } {{- end }} ` - - - result := make([]secretsmanagertypes.Filter, 0, len(m)) - - for k, v := range m { - filter := secretsmanagertypes.Filter{ - Key: secretsmanagertypes.FilterNameStringType(k), - Values: v, - } - - result = append(result, filter) - } - - return result -} From eeb9de8aa127a6e8effed8cd729a673a36bca024 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 11 Jan 2024 12:07:38 -0500 Subject: [PATCH 17/35] d/aws_secretsmanager_random_password: Tidy up. --- .../random_password_data_source.go | 63 +++++-------------- .../secretsmanager/service_package_gen.go | 3 +- 2 files changed, 19 insertions(+), 47 deletions(-) diff --git a/internal/service/secretsmanager/random_password_data_source.go b/internal/service/secretsmanager/random_password_data_source.go index fad43983092..e734225d3f5 100644 --- a/internal/service/secretsmanager/random_password_data_source.go +++ b/internal/service/secretsmanager/random_password_data_source.go @@ -14,8 +14,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" ) -// @SDKDataSource("aws_secretsmanager_random_password") -func DataSourceRandomPassword() *schema.Resource { +// @SDKDataSource("aws_secretsmanager_random_password", name="Random Password") +func dataSourceRandomPassword() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceRandomPasswordRead, @@ -55,7 +55,6 @@ func DataSourceRandomPassword() *schema.Resource { }, "random_password": { Type: schema.TypeString, - Optional: true, Computed: true, }, }, @@ -66,57 +65,29 @@ func dataSourceRandomPasswordRead(ctx context.Context, d *schema.ResourceData, m var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - var excludeCharacters string - if v, ok := d.GetOk("exclude_characters"); ok { - excludeCharacters = v.(string) - } - var excludeLowercase bool - if v, ok := d.GetOk("exclude_lowercase"); ok { - excludeLowercase = v.(bool) - } - var excludeNumbers bool - if v, ok := d.GetOk("exclude_numbers"); ok { - excludeNumbers = v.(bool) - } - var excludePunctuation bool - if v, ok := d.GetOk("exclude_punctuation"); ok { - excludePunctuation = v.(bool) - } - var excludeUppercase bool - if v, ok := d.GetOk("exclude_uppercase"); ok { - excludeUppercase = v.(bool) - } - var includeSpace bool - if v, ok := d.GetOk("exclude_space"); ok { - includeSpace = v.(bool) - } - var passwordLength int64 - if v, ok := d.GetOk("password_length"); ok { - passwordLength = int64(v.(int)) - } - var requireEachIncludedType bool - if v, ok := d.GetOk("require_each_included_type"); ok { - requireEachIncludedType = v.(bool) + input := &secretsmanager.GetRandomPasswordInput{ + ExcludeLowercase: aws.Bool(d.Get("exclude_lowercase").(bool)), + ExcludeNumbers: aws.Bool(d.Get("exclude_numbers").(bool)), + ExcludePunctuation: aws.Bool(d.Get("exclude_punctuation").(bool)), + ExcludeUppercase: aws.Bool(d.Get("exclude_uppercase").(bool)), + IncludeSpace: aws.Bool(d.Get("include_space").(bool)), + PasswordLength: aws.Int64(int64(d.Get("password_length").(int))), + RequireEachIncludedType: aws.Bool(d.Get("require_each_included_type").(bool)), } - input := &secretsmanager.GetRandomPasswordInput{ - ExcludeCharacters: aws.String(excludeCharacters), - ExcludeLowercase: aws.Bool(excludeLowercase), - ExcludeNumbers: aws.Bool(excludeNumbers), - ExcludePunctuation: aws.Bool(excludePunctuation), - ExcludeUppercase: aws.Bool(excludeUppercase), - IncludeSpace: aws.Bool(includeSpace), - PasswordLength: aws.Int64(passwordLength), - RequireEachIncludedType: aws.Bool(requireEachIncludedType), + if v, ok := d.GetOk("exclude_characters"); ok { + input.ExcludeCharacters = aws.String(v.(string)) } output, err := conn.GetRandomPassword(ctx, input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Get Random Password: %s", err) + return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Random Password: %s", err) } - d.SetId(aws.ToString(output.RandomPassword)) - d.Set("random_password", output.RandomPassword) + password := aws.ToString(output.RandomPassword) + d.SetId(password) + d.Set("random_password", password) return diags } diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index bf89ab48594..a1c4e693ff9 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -25,8 +25,9 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { return []*types.ServicePackageSDKDataSource{ { - Factory: DataSourceRandomPassword, + Factory: dataSourceRandomPassword, TypeName: "aws_secretsmanager_random_password", + Name: "Random Password", }, { Factory: DataSourceSecret, From 7fe825590f596bae02d1f93271de4e74530580c4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 11 Jan 2024 14:08:45 -0500 Subject: [PATCH 18/35] r/aws_secretsmanager_secret: Tidy up. --- .../service/secretsmanager/exports_test.go | 4 + internal/service/secretsmanager/secret.go | 377 +++++++++--------- .../service/secretsmanager/secret_policy.go | 55 ++- .../service/secretsmanager/secret_rotation.go | 2 +- .../secret_rotation_data_source.go | 2 +- .../service/secretsmanager/secret_test.go | 4 - .../secretsmanager/service_package_gen.go | 2 +- 7 files changed, 221 insertions(+), 225 deletions(-) diff --git a/internal/service/secretsmanager/exports_test.go b/internal/service/secretsmanager/exports_test.go index b820fd6c66e..49ee1c8ba5b 100644 --- a/internal/service/secretsmanager/exports_test.go +++ b/internal/service/secretsmanager/exports_test.go @@ -5,6 +5,10 @@ package secretsmanager // Exports for use in tests only. var ( + ResourceSecret = resourceSecret + + FindSecretByID = findSecretByID + ErrCodeResourceNotFoundException = errCodeResourceNotFoundException ErrCodeInvalidRequestException = errCodeInvalidRequestException ) diff --git a/internal/service/secretsmanager/secret.go b/internal/service/secretsmanager/secret.go index 06e96722408..a9cb865d354 100644 --- a/internal/service/secretsmanager/secret.go +++ b/internal/service/secretsmanager/secret.go @@ -14,7 +14,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" @@ -26,6 +25,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" tfiam "github.com/hashicorp/terraform-provider-aws/internal/service/iam" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -34,7 +34,7 @@ import ( // @SDKResource("aws_secretsmanager_secret", name="Secret") // @Tags(identifierAttribute="id") -func ResourceSecret() *schema.Resource { +func resourceSecret() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceSecretCreate, ReadWithoutTimeout: resourceSecretRead, @@ -104,7 +104,21 @@ func ResourceSecret() *schema.Resource { Type: schema.TypeSet, Optional: true, Computed: true, - Set: secretReplicaHash, + Set: func(v interface{}) int { + var buf bytes.Buffer + + m := v.(map[string]interface{}) + + if v, ok := m["kms_key_id"].(string); ok { + buf.WriteString(fmt.Sprintf("%s-", v)) + } + + if v, ok := m["region"].(string); ok { + buf.WriteString(fmt.Sprintf("%s-", v)) + } + + return create.StringHashcode(buf.String()) + }, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "kms_key_id": { @@ -143,12 +157,12 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - secretName := create.Name(d.Get("name").(string), d.Get("name_prefix").(string)) + name := create.Name(d.Get("name").(string), d.Get("name_prefix").(string)) input := &secretsmanager.CreateSecretInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries Description: aws.String(d.Get("description").(string)), ForceOverwriteReplicaSecret: d.Get("force_overwrite_replica_secret").(bool), - Name: aws.String(secretName), + Name: aws.String(name), Tags: getTagsIn(ctx), } @@ -157,40 +171,43 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte } if v, ok := d.GetOk("replica"); ok && v.(*schema.Set).Len() > 0 { - input.AddReplicaRegions = expandSecretReplicas(v.(*schema.Set).List()) + input.AddReplicaRegions = expandReplicaRegionTypes(v.(*schema.Set).List()) } - log.Printf("[DEBUG] Creating Secrets Manager Secret: %v", input) + // Retry for secret recreation after deletion. + outputRaw, err := tfresource.RetryWhen(ctx, PropagationTimeout, + func() (interface{}, error) { + return conn.CreateSecret(ctx, input) + }, + func(err error) (bool, error) { + // Temporarily retry on these errors to support immediate secret recreation: + // InvalidRequestException: You can’t perform this operation on the secret because it was deleted. + // InvalidRequestException: You can't create this secret because a secret with this name is already scheduled for deletion. + if errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "scheduled for deletion") || errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "was deleted") { + return true, err + } + return false, err + }, + ) - // Retry for secret recreation after deletion - var output *secretsmanager.CreateSecretOutput - err := retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { - var err error - output, err = conn.CreateSecret(ctx, input) - // Temporarily retry on these errors to support immediate secret recreation: - // InvalidRequestException: You can’t perform this operation on the secret because it was deleted. - // InvalidRequestException: You can't create this secret because a secret with this name is already scheduled for deletion. - if errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "scheduled for deletion") || errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "was deleted") { - return retry.RetryableError(err) - } - if err != nil { - return retry.NonRetryableError(err) - } - return nil - }) - if tfresource.TimedOut(err) { - output, err = conn.CreateSecret(ctx, input) - } if err != nil { - return sdkdiag.AppendErrorf(diags, "creating Secrets Manager Secret: %s", err) + return sdkdiag.AppendErrorf(diags, "creating Secrets Manager Secret (%s): %s", name, err) } - d.SetId(aws.ToString(output.ARN)) + d.SetId(aws.ToString(outputRaw.(*secretsmanager.CreateSecretOutput).ARN)) + + _, err = tfresource.RetryWhenNotFound(ctx, PropagationTimeout, func() (interface{}, error) { + return findSecretByID(ctx, conn, d.Id()) + }) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Secrets Manager Secret (%s) create: %s", d.Id(), err) + } if v, ok := d.GetOk("policy"); ok && v.(string) != "" && v.(string) != "{}" { policy, err := structure.NormalizeJsonString(v.(string)) if err != nil { - return sdkdiag.AppendErrorf(diags, "policy (%s) is invalid JSON: %s", v.(string), err) + return sdkdiag.AppendFromErr(diags, err) } input := &secretsmanager.PutResourcePolicyInput{ @@ -198,22 +215,8 @@ func resourceSecretCreate(ctx context.Context, d *schema.ResourceData, meta inte SecretId: aws.String(d.Id()), } - err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { - _, err := conn.PutResourcePolicy(ctx, input) - if errs.IsAErrorMessageContains[*types.MalformedPolicyDocumentException](err, - "This resource policy contains an unsupported principal") { - return retry.RetryableError(err) - } - if err != nil { - return retry.NonRetryableError(err) - } - return nil - }) - if tfresource.TimedOut(err) { - _, err = conn.PutResourcePolicy(ctx, input) - } - if err != nil { - return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret %q policy: %s", d.Id(), err) + if _, err := putSecretPolicy(ctx, conn, input); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } @@ -224,9 +227,7 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, PropagationTimeout, func() (interface{}, error) { - return FindSecretByID(ctx, conn, d.Id()) - }, d.IsNewResource()) + output, err := findSecretByID(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Secrets Manager Secret (%s) not found, removing from state", d.Id()) @@ -238,39 +239,34 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s): %s", d.Id(), err) } - output := outputRaw.(*secretsmanager.DescribeSecretOutput) - d.Set("arn", output.ARN) d.Set("description", output.Description) d.Set("kms_key_id", output.KmsKeyId) d.Set("name", output.Name) d.Set("name_prefix", create.NamePrefixFromName(aws.ToString(output.Name))) - - if err := d.Set("replica", flattenSecretReplicas(output.ReplicationStatus)); err != nil { + if err := d.Set("replica", flattenReplicationStatusTypes(output.ReplicationStatus)); err != nil { return sdkdiag.AppendErrorf(diags, "setting replica: %s", err) } var policy *secretsmanager.GetResourcePolicyOutput err = tfresource.Retry(ctx, PropagationTimeout, func() *retry.RetryError { - var err error - policy, err = conn.GetResourcePolicy(ctx, &secretsmanager.GetResourcePolicyInput{ - SecretId: aws.String(d.Id()), - }) + output, err := findSecretPolicyByID(ctx, conn, d.Id()) + if err != nil { return retry.NonRetryableError(err) } - if policy.ResourcePolicy != nil { - valid, err := tfiam.PolicyHasValidAWSPrincipals(aws.ToString(policy.ResourcePolicy)) - if err != nil { + if v := output.ResourcePolicy; v != nil { + if valid, err := tfiam.PolicyHasValidAWSPrincipals(aws.ToString(v)); err != nil { return retry.NonRetryableError(err) - } - if !valid { + } else if !valid { log.Printf("[DEBUG] Retrying because of invalid principals") return retry.RetryableError(errors.New("contains invalid principals")) } } + policy = output + return nil }) @@ -279,7 +275,7 @@ func resourceSecretRead(ctx context.Context, d *schema.ResourceData, meta interf } else if v := policy.ResourcePolicy; v != nil { policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.ToString(v)) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) @@ -298,20 +294,18 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte if d.HasChange("replica") { o, n := d.GetChange("replica") + os, ns := o.(*schema.Set), n.(*schema.Set) - os := o.(*schema.Set) - ns := n.(*schema.Set) - - err := removeSecretReplicas(ctx, conn, d.Id(), os.Difference(ns).List()) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting Secrets Manager Secret (%s) replica: %s", d.Id(), err) + if del := os.Difference(ns).List(); len(del) > 0 { + if err := removeSecretReplicas(ctx, conn, d.Id(), expandReplicaRegionTypes(del)); err != nil { + return sdkdiag.AppendFromErr(diags, err) + } } - err = addSecretReplicas(ctx, conn, d.Id(), d.Get("force_overwrite_replica_secret").(bool), ns.Difference(os).List()) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "adding Secrets Manager Secret (%s) replica: %s", d.Id(), err) + if add := ns.Difference(os).List(); len(add) > 0 { + if err := addSecretReplicas(ctx, conn, d.Id(), d.Get("force_overwrite_replica_secret").(bool), expandReplicaRegionTypes(add)); err != nil { + return sdkdiag.AppendFromErr(diags, err) + } } } @@ -326,7 +320,6 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte input.KmsKeyId = aws.String(v.(string)) } - log.Printf("[DEBUG] Updating Secrets Manager Secret: %v", input) _, err := conn.UpdateSecret(ctx, input) if err != nil { @@ -338,7 +331,7 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte if v, ok := d.GetOk("policy"); ok && v.(string) != "" && v.(string) != "{}" { policy, err := structure.NormalizeJsonString(v.(string)) if err != nil { - return sdkdiag.AppendErrorf(diags, "policy contains an invalid JSON: %s", err) + return sdkdiag.AppendFromErr(diags, err) } input := &secretsmanager.PutResourcePolicyInput{ @@ -346,24 +339,12 @@ func resourceSecretUpdate(ctx context.Context, d *schema.ResourceData, meta inte SecretId: aws.String(d.Id()), } - log.Printf("[DEBUG] Setting Secrets Manager Secret resource policy: %v", input) - _, err = tfresource.RetryWhenAWSErrMessageContains(ctx, PropagationTimeout, - func() (interface{}, error) { - return conn.PutResourcePolicy(ctx, input) - }, - errCodeMalformedPolicyDocumentException, "This resource policy contains an unsupported principal") - - if err != nil { - return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret (%s) policy: %s", d.Id(), err) + if _, err := putSecretPolicy(ctx, conn, input); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } else { - log.Printf("[DEBUG] Removing Secrets Manager Secret policy: %s", d.Id()) - _, err := conn.DeleteResourcePolicy(ctx, &secretsmanager.DeleteResourcePolicyInput{ - SecretId: aws.String(d.Id()), - }) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "removing Secrets Manager Secret (%s) policy: %s", d.Id(), err) + if err := deleteSecretPolicy(ctx, conn, d.Id()); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } } @@ -376,10 +357,8 @@ func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta inte conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) if v, ok := d.GetOk("replica"); ok && v.(*schema.Set).Len() > 0 { - err := removeSecretReplicas(ctx, conn, d.Id(), v.(*schema.Set).List()) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting Secrets Manager Secret (%s) replica: %s", d.Id(), err) + if err := removeSecretReplicas(ctx, conn, d.Id(), expandReplicaRegionTypes(v.(*schema.Set).List())); err != nil { + return sdkdiag.AppendFromErr(diags, err) } } @@ -387,17 +366,16 @@ func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta inte SecretId: aws.String(d.Id()), } - recoveryWindowInDays := d.Get("recovery_window_in_days").(int) - if recoveryWindowInDays == 0 { + if v := d.Get("recovery_window_in_days").(int); v == 0 { input.ForceDeleteWithoutRecovery = aws.Bool(true) } else { - input.RecoveryWindowInDays = aws.Int64(int64(recoveryWindowInDays)) + input.RecoveryWindowInDays = aws.Int64(int64(v)) } log.Printf("[DEBUG] Deleting Secrets Manager Secret: %s", d.Id()) _, err := conn.DeleteSecret(ctx, input) - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { + if errs.IsA[*types.ResourceNotFoundException](err) { return diags } @@ -406,7 +384,7 @@ func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta inte } _, err = tfresource.RetryUntilNotFound(ctx, PropagationTimeout, func() (interface{}, error) { - return FindSecretByID(ctx, conn, d.Id()) + return findSecretByID(ctx, conn, d.Id()) }) if err != nil { @@ -416,64 +394,124 @@ func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta inte return diags } -func removeSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id string, tfList []interface{}) error { - if len(tfList) == 0 { +func addSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id string, forceOverwrite bool, replicas []types.ReplicaRegionType) error { + if len(replicas) == 0 { return nil } - input := &secretsmanager.RemoveRegionsFromReplicationInput{ - SecretId: aws.String(id), + input := &secretsmanager.ReplicateSecretToRegionsInput{ + AddReplicaRegions: replicas, + SecretId: aws.String(id), + ForceOverwriteReplicaSecret: forceOverwrite, } - var regions []string + _, err := conn.ReplicateSecretToRegions(ctx, input) - for _, tfMapRaw := range tfList { - tfMap, ok := tfMapRaw.(map[string]interface{}) + if err != nil { + return fmt.Errorf("adding Secrets Manager Secret (%s) replicas: %w", id, err) + } - if !ok { - continue - } + return nil +} - regions = append(regions, tfMap["region"].(string)) - } +func removeSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id string, replicas []types.ReplicaRegionType) error { + regions := tfslices.ApplyToAll(replicas, func(v types.ReplicaRegionType) string { + return aws.ToString(v.Region) + }) - input.RemoveReplicaRegions = regions + if len(regions) == 0 { + return nil + } - log.Printf("[DEBUG] Removing Secrets Manager Secret Replicas: %v", input) + input := &secretsmanager.RemoveRegionsFromReplicationInput{ + RemoveReplicaRegions: regions, + SecretId: aws.String(id), + } _, err := conn.RemoveRegionsFromReplication(ctx, input) + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil + } + if err != nil { - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - return nil - } + return fmt.Errorf("removing Secrets Manager Secret (%s) replicas: %w", id, err) + } + + return nil +} + +func putSecretPolicy(ctx context.Context, conn *secretsmanager.Client, input *secretsmanager.PutResourcePolicyInput) (*secretsmanager.PutResourcePolicyOutput, error) { + outputRaw, err := tfresource.RetryWhenIsAErrorMessageContains[*types.MalformedPolicyDocumentException](ctx, PropagationTimeout, func() (interface{}, error) { + return conn.PutResourcePolicy(ctx, input) + }, "This resource policy contains an unsupported principal") - return err + if err != nil { + return nil, fmt.Errorf("putting Secrets Manager Secret (%s) policy: %w", aws.ToString(input.SecretId), err) + } + + return outputRaw.(*secretsmanager.PutResourcePolicyOutput), nil +} + +func deleteSecretPolicy(ctx context.Context, conn *secretsmanager.Client, id string) error { + input := &secretsmanager.DeleteResourcePolicyInput{ + SecretId: aws.String(id), + } + + _, err := conn.DeleteResourcePolicy(ctx, input) + + if err != nil { + return fmt.Errorf("deleting Secrets Manager Secret (%s) policy: %w", id, err) } return nil } -func addSecretReplicas(ctx context.Context, conn *secretsmanager.Client, id string, forceOverwrite bool, tfList []interface{}) error { - if len(tfList) == 0 { - return nil +func findSecret(ctx context.Context, conn *secretsmanager.Client, input *secretsmanager.DescribeSecretInput) (*secretsmanager.DescribeSecretOutput, error) { + output, err := conn.DescribeSecret(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } } - input := &secretsmanager.ReplicateSecretToRegionsInput{ - SecretId: aws.String(id), - ForceOverwriteReplicaSecret: forceOverwrite, - AddReplicaRegions: expandSecretReplicas(tfList), + if err != nil { + return nil, err } - log.Printf("[DEBUG] Removing Secrets Manager Secret Replica: %v", input) + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } - _, err := conn.ReplicateSecretToRegions(ctx, input) + return output, nil +} + +func findSecretByID(ctx context.Context, conn *secretsmanager.Client, id string) (*secretsmanager.DescribeSecretOutput, error) { + input := &secretsmanager.DescribeSecretInput{ + SecretId: aws.String(id), + } + + output, err := findSecret(ctx, conn, input) + + if err != nil { + return nil, err + } + + if output.DeletedDate != nil { + return nil, &retry.NotFoundError{LastRequest: input} + } - return err + return output, nil } -func expandSecretReplica(tfMap map[string]interface{}) types.ReplicaRegionType { - apiObject := types.ReplicaRegionType{} +func expandReplicaRegionType(tfMap map[string]interface{}) *types.ReplicaRegionType { + if tfMap == nil { + return nil + } + + apiObject := &types.ReplicaRegionType{} if v, ok := tfMap["kms_key_id"].(string); ok && v != "" { apiObject.KmsKeyId = aws.String(v) @@ -486,7 +524,7 @@ func expandSecretReplica(tfMap map[string]interface{}) types.ReplicaRegionType { return apiObject } -func expandSecretReplicas(tfList []interface{}) []types.ReplicaRegionType { +func expandReplicaRegionTypes(tfList []interface{}) []types.ReplicaRegionType { if len(tfList) == 0 { return nil } @@ -504,16 +542,22 @@ func expandSecretReplicas(tfList []interface{}) []types.ReplicaRegionType { continue } - apiObject := expandSecretReplica(tfMap) + apiObject := expandReplicaRegionType(tfMap) - apiObjects = append(apiObjects, apiObject) + if apiObject == nil { + continue + } + + apiObjects = append(apiObjects, *apiObject) } return apiObjects } -func flattenSecretReplica(apiObject types.ReplicationStatusType) map[string]interface{} { - tfMap := map[string]interface{}{} +func flattenReplicationStatusType(apiObject types.ReplicationStatusType) map[string]interface{} { + tfMap := map[string]interface{}{ + "status": apiObject.Status, + } if v := apiObject.KmsKeyId; v != nil { tfMap["kms_key_id"] = aws.ToString(v) @@ -527,10 +571,6 @@ func flattenSecretReplica(apiObject types.ReplicationStatusType) map[string]inte tfMap["region"] = aws.ToString(v) } - if v := apiObject.Status; v != "" { - tfMap["status"] = v - } - if v := apiObject.StatusMessage; v != nil { tfMap["status_message"] = aws.ToString(v) } @@ -538,7 +578,7 @@ func flattenSecretReplica(apiObject types.ReplicationStatusType) map[string]inte return tfMap } -func flattenSecretReplicas(apiObjects []types.ReplicationStatusType) []interface{} { +func flattenReplicationStatusTypes(apiObjects []types.ReplicationStatusType) []interface{} { if len(apiObjects) == 0 { return nil } @@ -546,63 +586,8 @@ func flattenSecretReplicas(apiObjects []types.ReplicationStatusType) []interface var tfList []interface{} for _, apiObject := range apiObjects { - tfList = append(tfList, flattenSecretReplica(apiObject)) + tfList = append(tfList, flattenReplicationStatusType(apiObject)) } return tfList } - -func secretReplicaHash(v interface{}) int { - var buf bytes.Buffer - - m := v.(map[string]interface{}) - - if v, ok := m["kms_key_id"].(string); ok { - buf.WriteString(fmt.Sprintf("%s-", v)) - } - - if v, ok := m["region"].(string); ok { - buf.WriteString(fmt.Sprintf("%s-", v)) - } - - return create.StringHashcode(buf.String()) -} - -func findSecret(ctx context.Context, conn *secretsmanager.Client, input *secretsmanager.DescribeSecretInput) (*secretsmanager.DescribeSecretOutput, error) { - output, err := conn.DescribeSecret(ctx, input) - - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output, nil -} - -func FindSecretByID(ctx context.Context, conn *secretsmanager.Client, id string) (*secretsmanager.DescribeSecretOutput, error) { - input := &secretsmanager.DescribeSecretInput{ - SecretId: aws.String(id), - } - - output, err := findSecret(ctx, conn, input) - - if err != nil { - return nil, err - } - - if output.DeletedDate != nil { - return nil, &retry.NotFoundError{LastRequest: input} - } - - return output, nil -} diff --git a/internal/service/secretsmanager/secret_policy.go b/internal/service/secretsmanager/secret_policy.go index e2bb505343b..40c210f1710 100644 --- a/internal/service/secretsmanager/secret_policy.go +++ b/internal/service/secretsmanager/secret_policy.go @@ -7,8 +7,9 @@ import ( "context" "log" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" @@ -16,6 +17,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -64,7 +66,7 @@ func resourceSecretPolicyCreate(ctx context.Context, d *schema.ResourceData, met policy, err := structure.NormalizeJsonString(d.Get("policy").(string)) if err != nil { - return sdkdiag.AppendErrorf(diags, "policy (%s) is invalid JSON: %s", d.Get("policy").(string), err) + return sdkdiag.AppendFromErr(diags, err) } input := &secretsmanager.PutResourcePolicyInput{ @@ -76,29 +78,13 @@ func resourceSecretPolicyCreate(ctx context.Context, d *schema.ResourceData, met input.BlockPublicPolicy = aws.Bool(v.(bool)) } - log.Printf("[DEBUG] Setting Secrets Manager Secret resource policy; %#v", input) - var output *secretsmanager.PutResourcePolicyOutput + output, err := putSecretPolicy(ctx, conn, input) - err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { - var err error - output, err = conn.PutResourcePolicy(ctx, input) - if tfawserr.ErrMessageContains(err, errCodeMalformedPolicyDocumentException, - "This resource policy contains an unsupported principal") { - return retry.RetryableError(err) - } - if err != nil { - return retry.NonRetryableError(err) - } - return nil - }) - if tfresource.TimedOut(err) { - output, err = conn.PutResourcePolicy(ctx, input) - } if err != nil { - return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret %q policy: %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } - d.SetId(aws.StringValue(output.ARN)) + d.SetId(aws.ToString(output.ARN)) return append(diags, resourceSecretPolicyRead(ctx, d, meta)...) } @@ -132,7 +118,7 @@ func resourceSecretPolicyRead(ctx context.Context, d *schema.ResourceData, meta } if output.ResourcePolicy != nil { - policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.StringValue(output.ResourcePolicy)) + policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.ToString(output.ResourcePolicy)) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Policy (%s): %s", d.Id(), err) } @@ -203,3 +189,28 @@ func resourceSecretPolicyDelete(ctx context.Context, d *schema.ResourceData, met return diags } + +func findSecretPolicyByID(ctx context.Context, conn *secretsmanager.Client, id string) (*secretsmanager.GetResourcePolicyOutput, error) { + input := &secretsmanager.GetResourcePolicyInput{ + SecretId: aws.String(id), + } + + output, err := conn.GetResourcePolicy(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} diff --git a/internal/service/secretsmanager/secret_rotation.go b/internal/service/secretsmanager/secret_rotation.go index 0f0cedd1fef..d8a427f31a1 100644 --- a/internal/service/secretsmanager/secret_rotation.go +++ b/internal/service/secretsmanager/secret_rotation.go @@ -115,7 +115,7 @@ func resourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, met conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, PropagationTimeout, func() (interface{}, error) { - return FindSecretByID(ctx, conn, d.Id()) + return findSecretByID(ctx, conn, d.Id()) }, d.IsNewResource()) if !d.IsNewResource() && tfresource.NotFound(err) { diff --git a/internal/service/secretsmanager/secret_rotation_data_source.go b/internal/service/secretsmanager/secret_rotation_data_source.go index e059517fee3..449b1cb4e63 100644 --- a/internal/service/secretsmanager/secret_rotation_data_source.go +++ b/internal/service/secretsmanager/secret_rotation_data_source.go @@ -62,7 +62,7 @@ func dataSourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, m conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) secretID := d.Get("secret_id").(string) - output, err := FindSecretByID(ctx, conn, secretID) + output, err := findSecretByID(ctx, conn, secretID) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s): %s", secretID, err) diff --git a/internal/service/secretsmanager/secret_test.go b/internal/service/secretsmanager/secret_test.go index 28809c7afb6..1f6c030798e 100644 --- a/internal/service/secretsmanager/secret_test.go +++ b/internal/service/secretsmanager/secret_test.go @@ -376,10 +376,6 @@ func testAccCheckSecretExists(ctx context.Context, n string, v *secretsmanager.D return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Secrets Manager Secret ID is set") - } - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) output, err := tfsecretsmanager.FindSecretByID(ctx, conn, rs.Primary.ID) diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index a1c4e693ff9..0c69cc74c46 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -51,7 +51,7 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ { - Factory: ResourceSecret, + Factory: resourceSecret, TypeName: "aws_secretsmanager_secret", Name: "Secret", Tags: &types.ServicePackageResourceTags{ From 1de939802b27158a2456cb1c5f641550bb53f486 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 11 Jan 2024 14:28:53 -0500 Subject: [PATCH 19/35] d/aws_secretsmanager_secret: Tidy up. --- .../secretsmanager/secret_data_source.go | 84 +++++++------------ .../secretsmanager/secret_data_source_test.go | 6 +- .../secretsmanager/service_package_gen.go | 3 +- 3 files changed, 34 insertions(+), 59 deletions(-) diff --git a/internal/service/secretsmanager/secret_data_source.go b/internal/service/secretsmanager/secret_data_source.go index 0ec9998cf88..315614c54b9 100644 --- a/internal/service/secretsmanager/secret_data_source.go +++ b/internal/service/secretsmanager/secret_data_source.go @@ -5,21 +5,18 @@ package secretsmanager import ( "context" - "log" - "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKDataSource("aws_secretsmanager_secret") -func DataSourceSecret() *schema.Resource { +// @SDKDataSource("aws_secretsmanager_secret", name="Secret") +func dataSourceSecret() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceSecretRead, @@ -29,6 +26,7 @@ func DataSourceSecret() *schema.Resource { Optional: true, Computed: true, ValidateFunc: verify.ValidARN, + ExactlyOneOf: []string{"arn", "name"}, }, "description": { Type: schema.TypeString, @@ -39,19 +37,16 @@ func DataSourceSecret() *schema.Resource { Computed: true, }, "name": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ExactlyOneOf: []string{"arn", "name"}, }, "policy": { Type: schema.TypeString, Computed: true, }, - "tags": { - Type: schema.TypeMap, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, + "tags": tftags.TagsSchemaComputed(), }, } } @@ -64,60 +59,39 @@ func dataSourceSecretRead(ctx context.Context, d *schema.ResourceData, meta inte var secretID string if v, ok := d.GetOk("arn"); ok { secretID = v.(string) - } - if v, ok := d.GetOk("name"); ok { - if secretID != "" { - return sdkdiag.AppendErrorf(diags, "specify only arn or name") - } + } else if v, ok := d.GetOk("name"); ok { secretID = v.(string) } - if secretID == "" { - return sdkdiag.AppendErrorf(diags, "must specify either arn or name") - } - - input := &secretsmanager.DescribeSecretInput{ - SecretId: aws.String(secretID), - } + secret, err := findSecretByID(ctx, conn, secretID) - log.Printf("[DEBUG] Reading Secrets Manager Secret: %v", input) - output, err := conn.DescribeSecret(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q not found", secretID) - } - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret: %s", err) + return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s): %s", secretID, err) } - if output.ARN == nil { - return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q not found", secretID) - } + arn := aws.ToString(secret.ARN) + d.SetId(arn) + d.Set("arn", arn) + d.Set("description", secret.Description) + d.Set("kms_key_id", secret.KmsKeyId) + d.Set("name", secret.Name) - d.SetId(aws.StringValue(output.ARN)) - d.Set("arn", output.ARN) - d.Set("description", output.Description) - d.Set("kms_key_id", output.KmsKeyId) - d.Set("name", output.Name) - d.Set("policy", "") + policy, err := findSecretPolicyByID(ctx, conn, d.Id()) - pIn := &secretsmanager.GetResourcePolicyInput{ - SecretId: aws.String(d.Id()), - } - log.Printf("[DEBUG] Reading Secrets Manager Secret policy: %v", pIn) - pOut, err := conn.GetResourcePolicy(ctx, pIn) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret policy: %s", err) - } - - if pOut != nil && pOut.ResourcePolicy != nil { - policy, err := structure.NormalizeJsonString(aws.StringValue(pOut.ResourcePolicy)) + return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s) policy: %s", d.Id(), err) + } else if v := policy.ResourcePolicy; v != nil { + policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.ToString(v)) if err != nil { - return sdkdiag.AppendErrorf(diags, "policy contains an invalid JSON: %s", err) + return sdkdiag.AppendFromErr(diags, err) } - d.Set("policy", policy) + + d.Set("policy", policyToSet) + } else { + d.Set("policy", "") } - if err := d.Set("tags", KeyValueTags(ctx, output.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { + if err := d.Set("tags", KeyValueTags(ctx, secret.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { return sdkdiag.AppendErrorf(diags, "setting tags: %s", err) } diff --git a/internal/service/secretsmanager/secret_data_source_test.go b/internal/service/secretsmanager/secret_data_source_test.go index 412943ca96a..4c2cf44c516 100644 --- a/internal/service/secretsmanager/secret_data_source_test.go +++ b/internal/service/secretsmanager/secret_data_source_test.go @@ -24,15 +24,15 @@ func TestAccSecretsManagerSecretDataSource_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccSecretDataSourceConfig_missingRequired, - ExpectError: regexache.MustCompile(`must specify either arn or name`), + ExpectError: regexache.MustCompile("one of `arn,name` must be specified"), }, { Config: testAccSecretDataSourceConfig_multipleSpecified, - ExpectError: regexache.MustCompile(`specify only arn or name`), + ExpectError: regexache.MustCompile("only one of `arn,name` can be specified"), }, { Config: testAccSecretDataSourceConfig_nonExistent, - ExpectError: regexache.MustCompile(`not found`), + ExpectError: regexache.MustCompile(`couldn't find resource`), }, }, }) diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index 0c69cc74c46..431e69177de 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -30,8 +30,9 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac Name: "Random Password", }, { - Factory: DataSourceSecret, + Factory: dataSourceSecret, TypeName: "aws_secretsmanager_secret", + Name: "Secret", }, { Factory: DataSourceSecretRotation, From 23667ce2540c02059a185ed000380551ae9a2aa5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 11 Jan 2024 15:42:53 -0500 Subject: [PATCH 20/35] r/aws_secretsmanager_secret_policy: Tidy up. --- .../service/secretsmanager/exports_test.go | 6 +- .../service/secretsmanager/secret_policy.go | 121 +++++++++--------- .../secretsmanager/secret_policy_test.go | 66 ++-------- .../secretsmanager/service_package_gen.go | 3 +- 4 files changed, 76 insertions(+), 120 deletions(-) diff --git a/internal/service/secretsmanager/exports_test.go b/internal/service/secretsmanager/exports_test.go index 49ee1c8ba5b..1e297976da8 100644 --- a/internal/service/secretsmanager/exports_test.go +++ b/internal/service/secretsmanager/exports_test.go @@ -5,9 +5,11 @@ package secretsmanager // Exports for use in tests only. var ( - ResourceSecret = resourceSecret + ResourceSecret = resourceSecret + ResourceSecretPolicy = resourceSecretPolicy - FindSecretByID = findSecretByID + FindSecretByID = findSecretByID + FindSecretPolicyByID = findSecretPolicyByID ErrCodeResourceNotFoundException = errCodeResourceNotFoundException ErrCodeInvalidRequestException = errCodeInvalidRequestException diff --git a/internal/service/secretsmanager/secret_policy.go b/internal/service/secretsmanager/secret_policy.go index 40c210f1710..88db21439a4 100644 --- a/internal/service/secretsmanager/secret_policy.go +++ b/internal/service/secretsmanager/secret_policy.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -23,23 +22,22 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_secretsmanager_secret_policy") -func ResourceSecretPolicy() *schema.Resource { +// @SDKResource("aws_secretsmanager_secret_policy", name="Secret Policy") +func resourceSecretPolicy() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceSecretPolicyCreate, ReadWithoutTimeout: resourceSecretPolicyRead, UpdateWithoutTimeout: resourceSecretPolicyUpdate, DeleteWithoutTimeout: resourceSecretPolicyDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, Schema: map[string]*schema.Schema{ - "secret_arn": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: verify.ValidARN, + "block_public_policy": { + Type: schema.TypeBool, + Optional: true, }, "policy": { Type: schema.TypeString, @@ -52,9 +50,11 @@ func ResourceSecretPolicy() *schema.Resource { return json }, }, - "block_public_policy": { - Type: schema.TypeBool, - Optional: true, + "secret_arn": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, }, }, } @@ -86,6 +86,14 @@ func resourceSecretPolicyCreate(ctx context.Context, d *schema.ResourceData, met d.SetId(aws.ToString(output.ARN)) + _, err = tfresource.RetryWhenNotFound(ctx, PropagationTimeout, func() (interface{}, error) { + return findSecretPolicyByID(ctx, conn, d.Id()) + }) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Secrets Manager Secret Policy (%s) create: %s", d.Id(), err) + } + return append(diags, resourceSecretPolicyRead(ctx, d, meta)...) } @@ -93,15 +101,9 @@ func resourceSecretPolicyRead(ctx context.Context, d *schema.ResourceData, meta var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - input := &secretsmanager.GetResourcePolicyInput{ - SecretId: aws.String(d.Id()), - } - - outputRaw, err := tfresource.RetryWhenNotFound(ctx, PropagationTimeout, func() (interface{}, error) { - return conn.GetResourcePolicy(ctx, input) - }) + output, err := findSecretPolicyByID(ctx, conn, d.Id()) - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { + if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Secrets Manager Secret Policy (%s) not found, removing from state", d.Id()) d.SetId("") return diags @@ -111,16 +113,13 @@ func resourceSecretPolicyRead(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Policy (%s): %s", d.Id(), err) } - output := outputRaw.(*secretsmanager.GetResourcePolicyOutput) - - if output == nil { - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Policy (%s): empty response", d.Id()) - } + // Empty (nil or "") policy indicates that the policy has been deleted. + // For backwards compatibility we don't check that. if output.ResourcePolicy != nil { policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.ToString(output.ResourcePolicy)) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Policy (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) @@ -136,35 +135,19 @@ func resourceSecretPolicyUpdate(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - if d.HasChanges("policy", "block_public_policy") { - policy, err := structure.NormalizeJsonString(d.Get("policy").(string)) - if err != nil { - return sdkdiag.AppendErrorf(diags, "policy contains an invalid JSON: %s", err) - } - input := &secretsmanager.PutResourcePolicyInput{ - ResourcePolicy: aws.String(policy), - SecretId: aws.String(d.Id()), - BlockPublicPolicy: aws.Bool(d.Get("block_public_policy").(bool)), - } + policy, err := structure.NormalizeJsonString(d.Get("policy").(string)) + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } - log.Printf("[DEBUG] Setting Secrets Manager Secret resource policy; %#v", input) - err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { - _, err := conn.PutResourcePolicy(ctx, input) - if tfawserr.ErrMessageContains(err, errCodeMalformedPolicyDocumentException, - "This resource policy contains an unsupported principal") { - return retry.RetryableError(err) - } - if err != nil { - return retry.NonRetryableError(err) - } - return nil - }) - if tfresource.TimedOut(err) { - _, err = conn.PutResourcePolicy(ctx, input) - } - if err != nil { - return sdkdiag.AppendErrorf(diags, "setting Secrets Manager Secret %q policy: %s", d.Id(), err) - } + input := &secretsmanager.PutResourcePolicyInput{ + ResourcePolicy: aws.String(policy), + SecretId: aws.String(d.Id()), + BlockPublicPolicy: aws.Bool(d.Get("block_public_policy").(bool)), + } + + if _, err := putSecretPolicy(ctx, conn, input); err != nil { + return sdkdiag.AppendFromErr(diags, err) } return append(diags, resourceSecretPolicyRead(ctx, d, meta)...) @@ -174,17 +157,33 @@ func resourceSecretPolicyDelete(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - input := &secretsmanager.DeleteResourcePolicyInput{ - SecretId: aws.String(d.Id()), + log.Printf("[DEBUG] Deleting Secrets Manager Secret Policy: %s", d.Id()) + err := deleteSecretPolicy(ctx, conn, d.Id()) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return diags } - log.Printf("[DEBUG] Removing Secrets Manager Secret policy: %#v", input) - _, err := conn.DeleteResourcePolicy(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - return diags + return sdkdiag.AppendFromErr(diags, err) + } + + _, err = tfresource.RetryUntilNotFound(ctx, PropagationTimeout, func() (interface{}, error) { + output, err := findSecretPolicyByID(ctx, conn, d.Id()) + + if err != nil { + return nil, err } - return sdkdiag.AppendErrorf(diags, "removing Secrets Manager Secret %q policy: %s", d.Id(), err) + + if aws.ToString(output.ResourcePolicy) == "" { + return nil, &retry.NotFoundError{} + } + + return output, nil + }) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Secrets Manager Secret Policy (%s) delete: %s", d.Id(), err) } return diags @@ -197,7 +196,7 @@ func findSecretPolicyByID(ctx context.Context, conn *secretsmanager.Client, id s output, err := conn.GetResourcePolicy(ctx, input) - if errs.IsA[*types.ResourceNotFoundException](err) { + if errs.IsA[*types.ResourceNotFoundException](err) || errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "You can't perform this operation on the secret because it was marked for deletion") { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, diff --git a/internal/service/secretsmanager/secret_policy_test.go b/internal/service/secretsmanager/secret_policy_test.go index 708b497f1da..de39653f7da 100644 --- a/internal/service/secretsmanager/secret_policy_test.go +++ b/internal/service/secretsmanager/secret_policy_test.go @@ -9,10 +9,8 @@ import ( "testing" "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -137,32 +135,9 @@ func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc continue } - secretInput := &secretsmanager.DescribeSecretInput{ - SecretId: aws.String(rs.Primary.ID), - } - - var output *secretsmanager.DescribeSecretOutput - - err := retry.RetryContext(ctx, tfsecretsmanager.PropagationTimeout, func() *retry.RetryError { - var err error - output, err = conn.DescribeSecret(ctx, secretInput) - - if err != nil { - return retry.NonRetryableError(err) - } - - if output != nil && output.DeletedDate == nil { - return retry.RetryableError(fmt.Errorf("Secret %q still exists", rs.Primary.ID)) - } + output, err := tfsecretsmanager.FindSecretPolicyByID(ctx, conn, rs.Primary.ID) - return nil - }) - - if tfresource.TimedOut(err) { - output, err = conn.DescribeSecret(ctx, secretInput) - } - - if tfawserr.ErrCodeEquals(err, tfsecretsmanager.ErrCodeResourceNotFoundException) { + if tfresource.NotFound(err) { continue } @@ -170,54 +145,33 @@ func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc return err } - if output != nil && output.DeletedDate == nil { - return fmt.Errorf("Secret %q still exists", rs.Primary.ID) - } - - input := &secretsmanager.GetResourcePolicyInput{ - SecretId: aws.String(rs.Primary.ID), - } - - _, err = conn.GetResourcePolicy(ctx, input) - - if tfawserr.ErrCodeEquals(err, tfsecretsmanager.ErrCodeResourceNotFoundException) || - tfawserr.ErrMessageContains(err, tfsecretsmanager.ErrCodeInvalidRequestException, - "You can't perform this operation on the secret because it was marked for deletion.") { + if aws.ToString(output.ResourcePolicy) == "" { continue } - if err != nil { - return err - } + return fmt.Errorf("Secrets Manager Secret Policy %s still exists", rs.Primary.ID) } return nil } } -func testAccCheckSecretPolicyExists(ctx context.Context, resourceName string, policy *secretsmanager.GetResourcePolicyOutput) resource.TestCheckFunc { +func testAccCheckSecretPolicyExists(ctx context.Context, n string, v *secretsmanager.GetResourcePolicyOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", resourceName) + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) - input := &secretsmanager.GetResourcePolicyInput{ - SecretId: aws.String(rs.Primary.ID), - } - output, err := conn.GetResourcePolicy(ctx, input) + output, err := tfsecretsmanager.FindSecretPolicyByID(ctx, conn, rs.Primary.ID) if err != nil { return err } - if output == nil { - return fmt.Errorf("Secret Policy %q does not exist", rs.Primary.ID) - } - - *policy = *output + *v = *output return nil } diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index 431e69177de..e7adf010873 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -60,8 +60,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceSecretPolicy, + Factory: resourceSecretPolicy, TypeName: "aws_secretsmanager_secret_policy", + Name: "Secret Policy", }, { Factory: ResourceSecretRotation, From 6bf98fbd9a6a57d0c20b0e812d537ac317494dcc Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 11 Jan 2024 15:54:31 -0500 Subject: [PATCH 21/35] Add 'verify.ValidBase64String'. --- internal/verify/validate.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/internal/verify/validate.go b/internal/verify/validate.go index cf2390c83cd..498bc4f86a9 100644 --- a/internal/verify/validate.go +++ b/internal/verify/validate.go @@ -141,6 +141,18 @@ func ValidAccountID(v interface{}, k string) (ws []string, errors []error) { return } +func ValidBase64String(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if !IsBase64Encoded([]byte(value)) { + errors = append(errors, fmt.Errorf( + "%q (%q) must be base64-encoded", + k, value)) + } + + return +} + // ValidCIDRNetworkAddress ensures that the string value is a valid CIDR that // represents a network address - it adds an error otherwise func ValidCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) { From 2dee720e25cea909a50a0874032e5092371cd6a5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 11 Jan 2024 17:29:16 -0500 Subject: [PATCH 22/35] Add 'TestAccSecretsManagerSecretPolicy_Disappears_secret' and 'TestAccSecretsManagerSecret_disappears'. --- .../service/secretsmanager/secret_policy.go | 2 +- .../secretsmanager/secret_policy_test.go | 25 ++++++++++++++++++ .../service/secretsmanager/secret_test.go | 26 ++++++++++++++++++- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/internal/service/secretsmanager/secret_policy.go b/internal/service/secretsmanager/secret_policy.go index 88db21439a4..2a91ade7405 100644 --- a/internal/service/secretsmanager/secret_policy.go +++ b/internal/service/secretsmanager/secret_policy.go @@ -160,7 +160,7 @@ func resourceSecretPolicyDelete(ctx context.Context, d *schema.ResourceData, met log.Printf("[DEBUG] Deleting Secrets Manager Secret Policy: %s", d.Id()) err := deleteSecretPolicy(ctx, conn, d.Id()) - if errs.IsA[*types.ResourceNotFoundException](err) { + if errs.IsA[*types.ResourceNotFoundException](err) || errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "You can't perform this operation on the secret because it was marked for deletion") { return diags } diff --git a/internal/service/secretsmanager/secret_policy_test.go b/internal/service/secretsmanager/secret_policy_test.go index de39653f7da..c6125c0b407 100644 --- a/internal/service/secretsmanager/secret_policy_test.go +++ b/internal/service/secretsmanager/secret_policy_test.go @@ -126,6 +126,31 @@ func TestAccSecretsManagerSecretPolicy_disappears(t *testing.T) { }) } +func TestAccSecretsManagerSecretPolicy_Disappears_secret(t *testing.T) { + ctx := acctest.Context(t) + var policy secretsmanager.GetResourcePolicyOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_secretsmanager_secret_policy.test" + secretResourceName := "aws_secretsmanager_secret.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretPolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretPolicyConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretPolicyExists(ctx, resourceName, &policy), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsecretsmanager.ResourceSecret(), secretResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckSecretPolicyDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) diff --git a/internal/service/secretsmanager/secret_test.go b/internal/service/secretsmanager/secret_test.go index 1f6c030798e..cfdf38a0f22 100644 --- a/internal/service/secretsmanager/secret_test.go +++ b/internal/service/secretsmanager/secret_test.go @@ -34,7 +34,7 @@ func TestAccSecretsManagerSecret_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccSecretConfig_name(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckSecretExists(ctx, resourceName, &secret), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "secretsmanager", regexache.MustCompile(fmt.Sprintf("secret:%s-[[:alnum:]]+$", rName))), resource.TestCheckResourceAttr(resourceName, "description", ""), @@ -85,6 +85,30 @@ func TestAccSecretsManagerSecret_withNamePrefix(t *testing.T) { }) } +func TestAccSecretsManagerSecret_disappears(t *testing.T) { + ctx := acctest.Context(t) + var secret secretsmanager.DescribeSecretOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_secretsmanager_secret.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretConfig_name(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretExists(ctx, resourceName, &secret), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsecretsmanager.ResourceSecret(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccSecretsManagerSecret_description(t *testing.T) { ctx := acctest.Context(t) var secret secretsmanager.DescribeSecretOutput From 924a79e7ba64361ce0ee88490fbc8344e4383bce Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 11 Jan 2024 17:34:50 -0500 Subject: [PATCH 23/35] r/aws_secretsmanager_secret_version: Tidy up. --- .../service/secretsmanager/exports_test.go | 10 +- .../service/secretsmanager/secret_version.go | 244 ++++++++++-------- .../secretsmanager/secret_version_test.go | 119 +++++---- .../secretsmanager/service_package_gen.go | 3 +- 4 files changed, 206 insertions(+), 170 deletions(-) diff --git a/internal/service/secretsmanager/exports_test.go b/internal/service/secretsmanager/exports_test.go index 1e297976da8..74cb41bfc80 100644 --- a/internal/service/secretsmanager/exports_test.go +++ b/internal/service/secretsmanager/exports_test.go @@ -5,11 +5,13 @@ package secretsmanager // Exports for use in tests only. var ( - ResourceSecret = resourceSecret - ResourceSecretPolicy = resourceSecretPolicy + ResourceSecret = resourceSecret + ResourceSecretPolicy = resourceSecretPolicy + ResourceSecretVersion = resourceSecretVersion - FindSecretByID = findSecretByID - FindSecretPolicyByID = findSecretPolicyByID + FindSecretByID = findSecretByID + FindSecretPolicyByID = findSecretPolicyByID + FindSecretVersionByTwoPartKey = findSecretVersionByTwoPartKey ErrCodeResourceNotFoundException = errCodeResourceNotFoundException ErrCodeInvalidRequestException = errCodeInvalidRequestException diff --git a/internal/service/secretsmanager/secret_version.go b/internal/service/secretsmanager/secret_version.go index 8e2d89ec83d..8dba67054fb 100644 --- a/internal/service/secretsmanager/secret_version.go +++ b/internal/service/secretsmanager/secret_version.go @@ -10,26 +10,29 @@ import ( "log" "strings" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/flex" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_secretsmanager_secret_version") -func ResourceSecretVersion() *schema.Resource { +// @SDKResource("aws_secretsmanager_secret_version", name="Secret Version") +func resourceSecretVersion() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceSecretVersionCreate, ReadWithoutTimeout: resourceSecretVersionRead, UpdateWithoutTimeout: resourceSecretVersionUpdate, DeleteWithoutTimeout: resourceSecretVersionDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -44,19 +47,20 @@ func ResourceSecretVersion() *schema.Resource { Required: true, ForceNew: true, }, - "secret_string": { + "secret_binary": { Type: schema.TypeString, Optional: true, ForceNew: true, Sensitive: true, - ConflictsWith: []string{"secret_binary"}, + ConflictsWith: []string{"secret_string"}, + ValidateFunc: verify.ValidBase64String, }, - "secret_binary": { + "secret_string": { Type: schema.TypeString, Optional: true, ForceNew: true, Sensitive: true, - ConflictsWith: []string{"secret_string"}, + ConflictsWith: []string{"secret_binary"}, }, "version_id": { Type: schema.TypeString, @@ -75,48 +79,44 @@ func ResourceSecretVersion() *schema.Resource { func resourceSecretVersionCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - secretID := d.Get("secret_id").(string) + secretID := d.Get("secret_id").(string) input := &secretsmanager.PutSecretValueInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries SecretId: aws.String(secretID), } - if v, ok := d.GetOk("secret_string"); ok { - input.SecretString = aws.String(v.(string)) - } - if v, ok := d.GetOk("secret_binary"); ok { - vs := []byte(v.(string)) - - if !verify.IsBase64Encoded(vs) { - return sdkdiag.AppendErrorf(diags, "expected base64 in secret_binary") - } - var err error input.SecretBinary, err = base64.StdEncoding.DecodeString(v.(string)) if err != nil { - return sdkdiag.AppendErrorf(diags, "decoding secret binary value: %s", err) + return sdkdiag.AppendFromErr(diags, err) } + } else if v, ok := d.GetOk("secret_string"); ok { + input.SecretString = aws.String(v.(string)) } - if v, ok := d.GetOk("version_stages"); ok { - versionStagesSet := v.(*schema.Set) - versionStages := make([]string, 0, versionStagesSet.Len()) - for _, stage := range versionStagesSet.List() { - versionStages = append(versionStages, stage.(string)) - } - input.VersionStages = versionStages + if v, ok := d.GetOk("version_stages"); ok && v.(*schema.Set).Len() > 0 { + input.VersionStages = flex.ExpandStringValueSet(v.(*schema.Set)) } - log.Printf("[DEBUG] Putting Secrets Manager Secret %q value", secretID) output, err := conn.PutSecretValue(ctx, input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "putting Secrets Manager Secret value: %s", err) + return sdkdiag.AppendErrorf(diags, "putting Secrets Manager Secret (%s) value: %s", secretID, err) } - d.SetId(fmt.Sprintf("%s|%s", secretID, aws.StringValue(output.VersionId))) + versionID := aws.ToString(output.VersionId) + d.SetId(secretVersionCreateResourceID(secretID, versionID)) + + _, err = tfresource.RetryWhenNotFound(ctx, PropagationTimeout, func() (interface{}, error) { + return findSecretVersionByTwoPartKey(ctx, conn, secretID, versionID) + }) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Secrets Manager Secret Version (%s) create: %s", d.Id(), err) + } return append(diags, resourceSecretVersionRead(ctx, d, meta)...) } @@ -125,49 +125,14 @@ func resourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - secretID, versionID, err := DecodeSecretVersionID(d.Id()) + secretID, versionID, err := secretVersionParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Version (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } - input := &secretsmanager.GetSecretValueInput{ - SecretId: aws.String(secretID), - VersionId: aws.String(versionID), - } - - var output *secretsmanager.GetSecretValueOutput - - err = retry.RetryContext(ctx, PropagationTimeout, func() *retry.RetryError { - var err error + output, err := findSecretVersionByTwoPartKey(ctx, conn, secretID, versionID) - output, err = conn.GetSecretValue(ctx, input) - - if d.IsNewResource() && tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - return retry.RetryableError(err) - } - - if d.IsNewResource() && tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { - return retry.RetryableError(err) - } - - if err != nil { - return retry.NonRetryableError(err) - } - - return nil - }) - - if tfresource.TimedOut(err) { - output, err = conn.GetSecretValue(ctx, input) - } - - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - log.Printf("[WARN] Secrets Manager Secret Version (%s) not found, removing from state", d.Id()) - d.SetId("") - return diags - } - - if !d.IsNewResource() && tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { + if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Secrets Manager Secret Version (%s) not found, removing from state", d.Id()) d.SetId("") return diags @@ -177,19 +142,12 @@ func resourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Version (%s): %s", d.Id(), err) } - if output == nil { - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Version (%s): empty response", d.Id()) - } - + d.Set("arn", output.ARN) + d.Set("secret_binary", verify.Base64Encode(output.SecretBinary)) d.Set("secret_id", secretID) d.Set("secret_string", output.SecretString) - d.Set("secret_binary", verify.Base64Encode(output.SecretBinary)) d.Set("version_id", output.VersionId) - d.Set("arn", output.ARN) - - if err := d.Set("version_stages", output.VersionStages); err != nil { - return sdkdiag.AppendErrorf(diags, "setting version_stages: %s", err) - } + d.Set("version_stages", output.VersionStages) return diags } @@ -198,46 +156,46 @@ func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, me var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - secretID, versionID, err := DecodeSecretVersionID(d.Id()) + secretID, versionID, err := secretVersionParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret Version (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } o, n := d.GetChange("version_stages") - os := o.(*schema.Set) - ns := n.(*schema.Set) - stagesToAdd := ns.Difference(os).List() - stagesToRemove := os.Difference(ns).List() + os, ns := o.(*schema.Set), n.(*schema.Set) + add, del := flex.ExpandStringValueSet(ns.Difference(os)), flex.ExpandStringValueSet(os.Difference(ns)) - for _, stage := range stagesToAdd { + for _, stage := range add { input := &secretsmanager.UpdateSecretVersionStageInput{ MoveToVersionId: aws.String(versionID), SecretId: aws.String(secretID), - VersionStage: aws.String(stage.(string)), + VersionStage: aws.String(stage), } - log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %v", input) _, err := conn.UpdateSecretVersionStage(ctx, input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) + return sdkdiag.AppendErrorf(diags, "adding Secrets Manager Secret Version (%s) stage (%s): %s", d.Id(), stage, err) } } - for _, stage := range stagesToRemove { + for _, stage := range del { // InvalidParameterException: You can only move staging label AWSCURRENT to a different secret version. It can’t be completely removed. - if stage.(string) == "AWSCURRENT" { + if stage == "AWSCURRENT" { log.Printf("[INFO] Skipping removal of AWSCURRENT staging label for secret %q version %q", secretID, versionID) continue } + input := &secretsmanager.UpdateSecretVersionStageInput{ RemoveFromVersionId: aws.String(versionID), SecretId: aws.String(secretID), - VersionStage: aws.String(stage.(string)), + VersionStage: aws.String(stage), } - log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %v", input) + _, err := conn.UpdateSecretVersionStage(ctx, input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) + return sdkdiag.AppendErrorf(diags, "deleting Secrets Manager Secret Version (%s) stage (%s): %s", d.Id(), stage, err) } } @@ -248,44 +206,104 @@ func resourceSecretVersionDelete(ctx context.Context, d *schema.ResourceData, me var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - secretID, versionID, err := DecodeSecretVersionID(d.Id()) + secretID, versionID, err := secretVersionParseResourceID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting Secrets Manager Secret Version (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } - if v, ok := d.GetOk("version_stages"); ok { - for _, stage := range v.(*schema.Set).List() { + if v, ok := d.GetOk("version_stages"); ok && v.(*schema.Set).Len() > 0 { + for _, stage := range flex.ExpandStringValueSet(v.(*schema.Set)) { // InvalidParameterException: You can only move staging label AWSCURRENT to a different secret version. It can’t be completely removed. - if stage.(string) == "AWSCURRENT" { + if stage == "AWSCURRENT" { log.Printf("[WARN] Cannot remove AWSCURRENT staging label, which may leave the secret %q version %q active", secretID, versionID) continue } + input := &secretsmanager.UpdateSecretVersionStageInput{ RemoveFromVersionId: aws.String(versionID), SecretId: aws.String(secretID), - VersionStage: aws.String(stage.(string)), + VersionStage: aws.String(stage), } - log.Printf("[DEBUG] Updating Secrets Manager Secret Version Stage: %v", input) + + log.Printf("[DEBUG] Deleting Secrets Manager Secret Version (%s) stage: %v", d.Id(), stage) _, err := conn.UpdateSecretVersionStage(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) || + errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "You can’t perform this operation on the secret because it was deleted") || + errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "You can't perform this operation on the secret because it was marked for deletion") { + return diags + } + if err != nil { - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - return diags - } - if tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") { - return diags - } - return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret %q Version Stage %q: %s", secretID, stage.(string), err) + return sdkdiag.AppendErrorf(diags, "deleting Secrets Manager Secret Version (%s) stage (%s): %s", d.Id(), stage, err) } } } + _, err = tfresource.RetryUntilNotFound(ctx, PropagationTimeout, func() (interface{}, error) { + output, err := findSecretVersionByTwoPartKey(ctx, conn, secretID, versionID) + + if err != nil { + return nil, err + } + + if len(output.VersionStages) == 0 || (len(output.VersionStages) == 1 && output.VersionStages[0] == "AWSCURRENT") { + return nil, &retry.NotFoundError{} + } + + return output, nil + }) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Secrets Manager Secret Version (%s) delete: %s", d.Id(), err) + } + return diags } -func DecodeSecretVersionID(id string) (string, string, error) { - idParts := strings.Split(id, "|") - if len(idParts) != 2 { - return "", "", fmt.Errorf("expected ID in format SecretID|VersionID, received: %s", id) +const secretVersionIDSeparator = "|" + +func secretVersionCreateResourceID(secretID, versionID string) string { + parts := []string{secretID, versionID} + id := strings.Join(parts, secretVersionIDSeparator) + + return id +} + +func secretVersionParseResourceID(id string) (string, string, error) { + parts := strings.SplitN(id, secretVersionIDSeparator, 2) + + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", "", fmt.Errorf("unexpected format of ID (%[1]s), expected SecretID%[2]sVersionID", id, secretVersionIDSeparator) } - return idParts[0], idParts[1], nil + + return parts[0], parts[1], nil +} + +func findSecretVersionByTwoPartKey(ctx context.Context, conn *secretsmanager.Client, secretID, versionID string) (*secretsmanager.GetSecretValueOutput, error) { + input := &secretsmanager.GetSecretValueInput{ + SecretId: aws.String(secretID), + VersionId: aws.String(versionID), + } + + output, err := conn.GetSecretValue(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) || + errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "You can’t perform this operation on the secret because it was deleted") || + errs.IsAErrorMessageContains[*types.InvalidRequestException](err, "You can't perform this operation on the secret because it was marked for deletion") { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil } diff --git a/internal/service/secretsmanager/secret_version_test.go b/internal/service/secretsmanager/secret_version_test.go index b6c2b0fee92..e9199d74488 100644 --- a/internal/service/secretsmanager/secret_version_test.go +++ b/internal/service/secretsmanager/secret_version_test.go @@ -9,14 +9,13 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" 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" tfsecretsmanager "github.com/hashicorp/terraform-provider-aws/internal/service/secretsmanager" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -139,6 +138,56 @@ func TestAccSecretsManagerSecretVersion_versionStages(t *testing.T) { }) } +func TestAccSecretsManagerSecretVersion_disappears(t *testing.T) { + ctx := acctest.Context(t) + var version secretsmanager.GetSecretValueOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_secretsmanager_secret_version.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretVersionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretVersionConfig_string(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretVersionExists(ctx, resourceName, &version), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsecretsmanager.ResourceSecretVersion(), resourceName), + ), + // Because resource Delete leaves a secret with a single stage ("AWSCURRENT"), the resource is still there. + // ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccSecretsManagerSecretVersion_Disappears_secret(t *testing.T) { + ctx := acctest.Context(t) + var version secretsmanager.GetSecretValueOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_secretsmanager_secret_version.test" + secretResourceName := "aws_secretsmanager_secret.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretVersionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretVersionConfig_string(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretVersionExists(ctx, resourceName, &version), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsecretsmanager.ResourceSecret(), secretResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckSecretVersionDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) @@ -148,77 +197,43 @@ func testAccCheckSecretVersionDestroy(ctx context.Context) resource.TestCheckFun continue } - secretID, versionID, err := tfsecretsmanager.DecodeSecretVersionID(rs.Primary.ID) - if err != nil { - return err - } + output, err := tfsecretsmanager.FindSecretVersionByTwoPartKey(ctx, conn, rs.Primary.Attributes["secret_id"], rs.Primary.Attributes["version_id"]) - input := &secretsmanager.GetSecretValueInput{ - SecretId: aws.String(secretID), - VersionId: aws.String(versionID), + if tfresource.NotFound(err) { + continue } - output, err := conn.GetSecretValue(ctx, input) - if err != nil { - if tfawserr.ErrCodeEquals(err, tfsecretsmanager.ErrCodeResourceNotFoundException) { - return nil - } - if tfawserr.ErrMessageContains(err, tfsecretsmanager.ErrCodeInvalidRequestException, "was deleted") || tfawserr.ErrMessageContains(err, tfsecretsmanager.ErrCodeInvalidRequestException, "was marked for deletion") { - return nil - } return err } - if output == nil { - return nil - } - - if len(output.VersionStages) == 0 { - return nil - } - - if len(output.VersionStages) == 1 && output.VersionStages[0] == "AWSCURRENT" { - return nil + if len(output.VersionStages) == 0 || (len(output.VersionStages) == 1 && output.VersionStages[0] == "AWSCURRENT") { + continue } - return fmt.Errorf("Secret Version %q still exists", rs.Primary.ID) + return fmt.Errorf("Secrets Manager Secret Version %s still exists", rs.Primary.ID) } return nil } } -func testAccCheckSecretVersionExists(ctx context.Context, resourceName string, version *secretsmanager.GetSecretValueOutput) resource.TestCheckFunc { +func testAccCheckSecretVersionExists(ctx context.Context, n string, v *secretsmanager.GetSecretValueOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - secretID, versionID, err := tfsecretsmanager.DecodeSecretVersionID(rs.Primary.ID) - if err != nil { - return err + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) - input := &secretsmanager.GetSecretValueInput{ - SecretId: aws.String(secretID), - VersionId: aws.String(versionID), - } - - output, err := conn.GetSecretValue(ctx, input) + output, err := tfsecretsmanager.FindSecretVersionByTwoPartKey(ctx, conn, rs.Primary.Attributes["secret_id"], rs.Primary.Attributes["version_id"]) if err != nil { return err } - if output == nil { - return fmt.Errorf("Secret Version %q does not exist", rs.Primary.ID) - } - - *version = *output + *v = *output return nil } @@ -227,7 +242,7 @@ func testAccCheckSecretVersionExists(ctx context.Context, resourceName string, v func testAccSecretVersionConfig_string(rName string) string { return fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { - name = "%s" + name = %[1]q } resource "aws_secretsmanager_secret_version" "test" { @@ -240,7 +255,7 @@ resource "aws_secretsmanager_secret_version" "test" { func testAccSecretVersionConfig_binary(rName string) string { return fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { - name = "%s" + name = %[1]q } resource "aws_secretsmanager_secret_version" "test" { @@ -253,7 +268,7 @@ resource "aws_secretsmanager_secret_version" "test" { func testAccSecretVersionConfig_stagesSingle(rName string) string { return fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { - name = "%s" + name = %[1]q } resource "aws_secretsmanager_secret_version" "test" { @@ -268,7 +283,7 @@ resource "aws_secretsmanager_secret_version" "test" { func testAccSecretVersionConfig_stagesSingleUpdated(rName string) string { return fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { - name = "%s" + name = %[1]q } resource "aws_secretsmanager_secret_version" "test" { @@ -283,7 +298,7 @@ resource "aws_secretsmanager_secret_version" "test" { func testAccSecretVersionConfig_stagesMultiple(rName string) string { return fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { - name = "%s" + name = %[1]q } resource "aws_secretsmanager_secret_version" "test" { diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index e7adf010873..8c00643a0a7 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -69,8 +69,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka TypeName: "aws_secretsmanager_secret_rotation", }, { - Factory: ResourceSecretVersion, + Factory: resourceSecretVersion, TypeName: "aws_secretsmanager_secret_version", + Name: "Secret Version", }, } } From 36e763e87c4ba54ed415c25bbfa6d8540977e31e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 10:18:55 -0500 Subject: [PATCH 24/35] d/aws_secretsmanager_secret_version: Tidy up. --- .../service/secretsmanager/secret_version.go | 28 +++++++----- .../secret_version_data_source.go | 45 +++++++------------ .../secret_version_data_source_test.go | 2 +- .../secretsmanager/service_package_gen.go | 3 +- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/internal/service/secretsmanager/secret_version.go b/internal/service/secretsmanager/secret_version.go index 8dba67054fb..017618d2b98 100644 --- a/internal/service/secretsmanager/secret_version.go +++ b/internal/service/secretsmanager/secret_version.go @@ -25,6 +25,10 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/verify" ) +const ( + secretVersionStageCurrent = "AWSCURRENT" +) + // @SDKResource("aws_secretsmanager_secret_version", name="Secret Version") func resourceSecretVersion() *schema.Resource { return &schema.Resource{ @@ -181,7 +185,7 @@ func resourceSecretVersionUpdate(ctx context.Context, d *schema.ResourceData, me for _, stage := range del { // InvalidParameterException: You can only move staging label AWSCURRENT to a different secret version. It can’t be completely removed. - if stage == "AWSCURRENT" { + if stage == secretVersionStageCurrent { log.Printf("[INFO] Skipping removal of AWSCURRENT staging label for secret %q version %q", secretID, versionID) continue } @@ -214,7 +218,7 @@ func resourceSecretVersionDelete(ctx context.Context, d *schema.ResourceData, me if v, ok := d.GetOk("version_stages"); ok && v.(*schema.Set).Len() > 0 { for _, stage := range flex.ExpandStringValueSet(v.(*schema.Set)) { // InvalidParameterException: You can only move staging label AWSCURRENT to a different secret version. It can’t be completely removed. - if stage == "AWSCURRENT" { + if stage == secretVersionStageCurrent { log.Printf("[WARN] Cannot remove AWSCURRENT staging label, which may leave the secret %q version %q active", secretID, versionID) continue } @@ -225,7 +229,7 @@ func resourceSecretVersionDelete(ctx context.Context, d *schema.ResourceData, me VersionStage: aws.String(stage), } - log.Printf("[DEBUG] Deleting Secrets Manager Secret Version (%s) stage: %v", d.Id(), stage) + log.Printf("[DEBUG] Deleting Secrets Manager Secret Version (%s) stage: %s", d.Id(), stage) _, err := conn.UpdateSecretVersionStage(ctx, input) if errs.IsA[*types.ResourceNotFoundException](err) || @@ -247,7 +251,7 @@ func resourceSecretVersionDelete(ctx context.Context, d *schema.ResourceData, me return nil, err } - if len(output.VersionStages) == 0 || (len(output.VersionStages) == 1 && output.VersionStages[0] == "AWSCURRENT") { + if len(output.VersionStages) == 0 || (len(output.VersionStages) == 1 && output.VersionStages[0] == secretVersionStageCurrent) { return nil, &retry.NotFoundError{} } @@ -280,12 +284,7 @@ func secretVersionParseResourceID(id string) (string, string, error) { return parts[0], parts[1], nil } -func findSecretVersionByTwoPartKey(ctx context.Context, conn *secretsmanager.Client, secretID, versionID string) (*secretsmanager.GetSecretValueOutput, error) { - input := &secretsmanager.GetSecretValueInput{ - SecretId: aws.String(secretID), - VersionId: aws.String(versionID), - } - +func findSecretVersion(ctx context.Context, conn *secretsmanager.Client, input *secretsmanager.GetSecretValueInput) (*secretsmanager.GetSecretValueOutput, error) { output, err := conn.GetSecretValue(ctx, input) if errs.IsA[*types.ResourceNotFoundException](err) || @@ -307,3 +306,12 @@ func findSecretVersionByTwoPartKey(ctx context.Context, conn *secretsmanager.Cli return output, nil } + +func findSecretVersionByTwoPartKey(ctx context.Context, conn *secretsmanager.Client, secretID, versionID string) (*secretsmanager.GetSecretValueOutput, error) { + input := &secretsmanager.GetSecretValueInput{ + SecretId: aws.String(secretID), + VersionId: aws.String(versionID), + } + + return findSecretVersion(ctx, conn, input) +} diff --git a/internal/service/secretsmanager/secret_version_data_source.go b/internal/service/secretsmanager/secret_version_data_source.go index 783e44ac904..77a3c806ed5 100644 --- a/internal/service/secretsmanager/secret_version_data_source.go +++ b/internal/service/secretsmanager/secret_version_data_source.go @@ -5,20 +5,17 @@ package secretsmanager import ( "context" - "fmt" - "log" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" ) -// @SDKDataSource("aws_secretsmanager_secret_version") -func DataSourceSecretVersion() *schema.Resource { +// @SDKDataSource("aws_secretsmanager_secret_version", name="Secret Version") +func dataSourceSecretVersion() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceSecretVersionRead, @@ -31,12 +28,12 @@ func DataSourceSecretVersion() *schema.Resource { Type: schema.TypeString, Required: true, }, - "secret_string": { + "secret_binary": { Type: schema.TypeString, Computed: true, Sensitive: true, }, - "secret_binary": { + "secret_string": { Type: schema.TypeString, Computed: true, Sensitive: true, @@ -49,7 +46,7 @@ func DataSourceSecretVersion() *schema.Resource { "version_stage": { Type: schema.TypeString, Optional: true, - Default: "AWSCURRENT", + Default: secretVersionStageCurrent, }, "version_stages": { Type: schema.TypeSet, @@ -63,9 +60,9 @@ func DataSourceSecretVersion() *schema.Resource { func dataSourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) + secretID := d.Get("secret_id").(string) var version string - input := &secretsmanager.GetSecretValueInput{ SecretId: aws.String(secretID), } @@ -74,34 +71,26 @@ func dataSourceSecretVersionRead(ctx context.Context, d *schema.ResourceData, me versionID := v.(string) input.VersionId = aws.String(versionID) version = versionID - } else { - versionStage := d.Get("version_stage").(string) + } else if v, ok := d.GetOk("version_stage"); ok { + versionStage := v.(string) input.VersionStage = aws.String(versionStage) version = versionStage } - log.Printf("[DEBUG] Reading Secrets Manager Secret Version: %v", input) - output, err := conn.GetSecretValue(ctx, input) + id := secretVersionCreateResourceID(secretID, version) + output, err := findSecretVersion(ctx, conn, input) + if err != nil { - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q Version %q not found", secretID, version) - } - if tfawserr.ErrMessageContains(err, errCodeInvalidRequestException, "You can't perform this operation on the secret because it was deleted") { - return sdkdiag.AppendErrorf(diags, "Secrets Manager Secret %q Version %q not found", secretID, version) - } - return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Version: %s", err) + return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Version (%s): %s", id, err) } - d.SetId(fmt.Sprintf("%s|%s", secretID, version)) + d.SetId(id) + d.Set("arn", output.ARN) d.Set("secret_id", secretID) + d.Set("secret_binary", string(output.SecretBinary)) d.Set("secret_string", output.SecretString) d.Set("version_id", output.VersionId) - d.Set("secret_binary", string(output.SecretBinary)) - d.Set("arn", output.ARN) - - if err := d.Set("version_stages", output.VersionStages); err != nil { - return sdkdiag.AppendErrorf(diags, "setting version_stages: %s", err) - } + d.Set("version_stages", output.VersionStages) return diags } diff --git a/internal/service/secretsmanager/secret_version_data_source_test.go b/internal/service/secretsmanager/secret_version_data_source_test.go index c5d9f3b70ee..2207998e5d3 100644 --- a/internal/service/secretsmanager/secret_version_data_source_test.go +++ b/internal/service/secretsmanager/secret_version_data_source_test.go @@ -28,7 +28,7 @@ func TestAccSecretsManagerSecretVersionDataSource_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccSecretVersionDataSourceConfig_nonExistent, - ExpectError: regexache.MustCompile(`not found`), + ExpectError: regexache.MustCompile(`couldn't find resource`), }, { Config: testAccSecretVersionDataSourceConfig_stageDefault(rName), diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index 8c00643a0a7..acd07c0d722 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -39,8 +39,9 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac TypeName: "aws_secretsmanager_secret_rotation", }, { - Factory: DataSourceSecretVersion, + Factory: dataSourceSecretVersion, TypeName: "aws_secretsmanager_secret_version", + Name: "Secret Version", }, { Factory: DataSourceSecrets, From d10988f3164d482470fe30b341d83249fa5141ea Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 10:29:12 -0500 Subject: [PATCH 25/35] d/aws_secretsmanager_secrets: Tidy up. --- .../secretsmanager/secrets_data_source.go | 19 +++++++---------- .../secrets_data_source_test.go | 21 +++++-------------- .../secretsmanager/service_package_gen.go | 3 ++- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/internal/service/secretsmanager/secrets_data_source.go b/internal/service/secretsmanager/secrets_data_source.go index 75c073dc040..a38ae67d89c 100644 --- a/internal/service/secretsmanager/secrets_data_source.go +++ b/internal/service/secretsmanager/secrets_data_source.go @@ -6,18 +6,19 @@ package secretsmanager import ( "context" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" - "github.com/aws/aws-sdk-go/aws" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/generate/namevaluesfiltersv2" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" ) -// @SDKDataSource("aws_secretsmanager_secrets") -func DataSourceSecrets() *schema.Resource { +// @SDKDataSource("aws_secretsmanager_secrets", name="Secrets") +func dataSourceSecrets() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceSecretsRead, Schema: map[string]*schema.Schema{ @@ -51,6 +52,7 @@ func dataSourceSecretsRead(ctx context.Context, d *schema.ResourceData, meta int paginator := secretsmanager.NewListSecretsPaginator(conn, input) for paginator.HasMorePages() { page, err := paginator.NextPage(ctx) + if err != nil { return sdkdiag.AppendErrorf(diags, "listing Secrets Manager Secrets: %s", err) } @@ -60,16 +62,9 @@ func dataSourceSecretsRead(ctx context.Context, d *schema.ResourceData, meta int } } - var arns, names []string - - for _, r := range results { - arns = append(arns, aws.StringValue(r.ARN)) - names = append(names, aws.StringValue(r.Name)) - } - d.SetId(meta.(*conns.AWSClient).Region) - d.Set("arns", arns) - d.Set("names", names) + d.Set("arns", tfslices.ApplyToAll(results, func(v types.SecretListEntry) string { return aws.ToString(v.ARN) })) + d.Set("names", tfslices.ApplyToAll(results, func(v types.SecretListEntry) string { return aws.ToString(v.Name) })) return diags } diff --git a/internal/service/secretsmanager/secrets_data_source_test.go b/internal/service/secretsmanager/secrets_data_source_test.go index 850591d7546..435b76a6219 100644 --- a/internal/service/secretsmanager/secrets_data_source_test.go +++ b/internal/service/secretsmanager/secrets_data_source_test.go @@ -5,13 +5,11 @@ package secretsmanager_test import ( "fmt" - "log" "testing" "time" 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/names" ) @@ -22,14 +20,6 @@ func TestAccSecretsManagerSecretsDataSource_filter(t *testing.T) { resourceName := "aws_secretsmanager_secret.test" dataSourceName := "data.aws_secretsmanager_secrets.test" - propagationSleep := func() resource.TestCheckFunc { - return func(s *terraform.State) error { - log.Print("[DEBUG] Test: Sleep to allow secrets become visible in the list.") - time.Sleep(30 * time.Second) - return nil - } - } - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), @@ -37,8 +27,9 @@ func TestAccSecretsManagerSecretsDataSource_filter(t *testing.T) { CheckDestroy: testAccCheckSecretDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccSecretsDataSourceConfig_filter2(rName), - Check: propagationSleep(), + Config: testAccSecretsDataSourceConfig_base(rName), + // Sleep to allow secrets become visible in the list. + Check: acctest.CheckSleep(t, 30*time.Second), }, { Config: testAccSecretsDataSourceConfig_filter(rName), @@ -53,7 +44,7 @@ func TestAccSecretsManagerSecretsDataSource_filter(t *testing.T) { }) } -func testAccSecretsDataSourceConfig_filter2(rName string) string { +func testAccSecretsDataSourceConfig_base(rName string) string { return fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { name = %[1]q @@ -62,9 +53,7 @@ resource "aws_secretsmanager_secret" "test" { } func testAccSecretsDataSourceConfig_filter(rName string) string { - return acctest.ConfigCompose( - testAccSecretsDataSourceConfig_filter2(rName), - ` + return acctest.ConfigCompose(testAccSecretsDataSourceConfig_base(rName), ` data "aws_secretsmanager_secrets" "test" { filter { name = "name" diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index acd07c0d722..7efefd82aed 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -44,8 +44,9 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac Name: "Secret Version", }, { - Factory: DataSourceSecrets, + Factory: dataSourceSecrets, TypeName: "aws_secretsmanager_secrets", + Name: "Secrets", }, } } From ce3897adea654205a8309584f5539df073c6012a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 11:18:35 -0500 Subject: [PATCH 26/35] r/aws_secretsmanager_secret_rotation: Tidy up. --- .../service/secretsmanager/exports_test.go | 7 +- .../service/secretsmanager/secret_rotation.go | 62 +++++---- .../secretsmanager/secret_rotation_test.go | 121 +++++++++++++----- .../secretsmanager/service_package_gen.go | 3 +- 4 files changed, 127 insertions(+), 66 deletions(-) diff --git a/internal/service/secretsmanager/exports_test.go b/internal/service/secretsmanager/exports_test.go index 74cb41bfc80..642c210b254 100644 --- a/internal/service/secretsmanager/exports_test.go +++ b/internal/service/secretsmanager/exports_test.go @@ -5,9 +5,10 @@ package secretsmanager // Exports for use in tests only. var ( - ResourceSecret = resourceSecret - ResourceSecretPolicy = resourceSecretPolicy - ResourceSecretVersion = resourceSecretVersion + ResourceSecret = resourceSecret + ResourceSecretPolicy = resourceSecretPolicy + ResourceSecretRotation = resourceSecretRotation + ResourceSecretVersion = resourceSecretVersion FindSecretByID = findSecretByID FindSecretPolicyByID = findSecretPolicyByID diff --git a/internal/service/secretsmanager/secret_rotation.go b/internal/service/secretsmanager/secret_rotation.go index d8a427f31a1..d4e84f36851 100644 --- a/internal/service/secretsmanager/secret_rotation.go +++ b/internal/service/secretsmanager/secret_rotation.go @@ -9,9 +9,9 @@ import ( "time" "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" - "github.com/aws/aws-sdk-go/aws" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -22,8 +22,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_secretsmanager_secret_rotation") -func ResourceSecretRotation() *schema.Resource { +// @SDKResource("aws_secretsmanager_secret_rotation", name="Secret Rotation") +func resourceSecretRotation() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceSecretRotationCreate, ReadWithoutTimeout: resourceSecretRotationRead, @@ -84,8 +84,8 @@ func ResourceSecretRotation() *schema.Resource { func resourceSecretRotationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - secretID := d.Get("secret_id").(string) + secretID := d.Get("secret_id").(string) input := &secretsmanager.RotateSecretInput{ ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries RotationRules: expandRotationRules(d.Get("rotation_rules").([]interface{})), @@ -105,7 +105,7 @@ func resourceSecretRotationCreate(ctx context.Context, d *schema.ResourceData, m return sdkdiag.AppendErrorf(diags, "creating Secrets Manager Secret Rotation (%s): %s", secretID, err) } - d.SetId(aws.StringValue(outputRaw.(*secretsmanager.RotateSecretOutput).ARN)) + d.SetId(aws.ToString(outputRaw.(*secretsmanager.RotateSecretOutput).ARN)) return append(diags, resourceSecretRotationRead(ctx, d, meta)...) } @@ -114,9 +114,7 @@ func resourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, met var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - outputRaw, err := tfresource.RetryWhenNewResourceNotFound(ctx, PropagationTimeout, func() (interface{}, error) { - return findSecretByID(ctx, conn, d.Id()) - }, d.IsNewResource()) + output, err := findSecretByID(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Secrets Manager Secret Rotation (%s) not found, removing from state", d.Id()) @@ -128,11 +126,9 @@ func resourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, met return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret Rotation (%s): %s", d.Id(), err) } - output := outputRaw.(*secretsmanager.DescribeSecretOutput) - - d.Set("secret_id", d.Id()) - d.Set("rotation_enabled", output.RotationEnabled) - if aws.BoolValue(output.RotationEnabled) { + rotationEnabled := aws.ToBool(output.RotationEnabled) + d.Set("rotation_enabled", rotationEnabled) + if rotationEnabled { d.Set("rotation_lambda_arn", output.RotationLambdaARN) if err := d.Set("rotation_rules", flattenRotationRules(output.RotationRules)); err != nil { return sdkdiag.AppendErrorf(diags, "setting rotation_rules: %s", err) @@ -141,6 +137,7 @@ func resourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, met d.Set("rotation_lambda_arn", "") d.Set("rotation_rules", []interface{}{}) } + d.Set("secret_id", d.Id()) return diags } @@ -148,27 +145,25 @@ func resourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, met func resourceSecretRotationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) - secretID := d.Get("secret_id").(string) - if d.HasChanges("rotation_lambda_arn", "rotation_rules") { - input := &secretsmanager.RotateSecretInput{ - ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries - RotationRules: expandRotationRules(d.Get("rotation_rules").([]interface{})), - SecretId: aws.String(secretID), - } + secretID := d.Get("secret_id").(string) + input := &secretsmanager.RotateSecretInput{ + ClientRequestToken: aws.String(id.UniqueId()), // Needed because we're handling our own retries + RotationRules: expandRotationRules(d.Get("rotation_rules").([]interface{})), + SecretId: aws.String(secretID), + } - if v, ok := d.GetOk("rotation_lambda_arn"); ok { - input.RotationLambdaARN = aws.String(v.(string)) - } + if v, ok := d.GetOk("rotation_lambda_arn"); ok { + input.RotationLambdaARN = aws.String(v.(string)) + } - // AccessDeniedException: Secrets Manager cannot invoke the specified Lambda function. - _, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, 1*time.Minute, func() (interface{}, error) { - return conn.RotateSecret(ctx, input) - }, "AccessDeniedException") + // AccessDeniedException: Secrets Manager cannot invoke the specified Lambda function. + _, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, 1*time.Minute, func() (interface{}, error) { + return conn.RotateSecret(ctx, input) + }, "AccessDeniedException") - if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret Rotation (%s): %s", d.Id(), err) - } + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating Secrets Manager Secret Rotation (%s): %s", d.Id(), err) } return append(diags, resourceSecretRotationRead(ctx, d, meta)...) @@ -178,6 +173,7 @@ func resourceSecretRotationDelete(ctx context.Context, d *schema.ResourceData, m var diags diag.Diagnostics conn := meta.(*conns.AWSClient).SecretsManagerClient(ctx) + log.Printf("[DEBUG] Deleting Secrets Manager Secret Rotation: %s", d.Id()) _, err := conn.CancelRotateSecret(ctx, &secretsmanager.CancelRotateSecretInput{ SecretId: aws.String(d.Get("secret_id").(string)), }) @@ -221,15 +217,15 @@ func flattenRotationRules(rules *types.RotationRulesType) []interface{} { if v := rules.AutomaticallyAfterDays; v != nil && rules.ScheduleExpression == nil { // Only populate automatically_after_days if schedule_expression is not set, otherwise we won't be able to update the resource - m["automatically_after_days"] = int(aws.Int64Value(v)) + m["automatically_after_days"] = int(aws.ToInt64(v)) } if v := rules.Duration; v != nil { - m["duration"] = aws.StringValue(v) + m["duration"] = aws.ToString(v) } if v := rules.ScheduleExpression; v != nil { - m["schedule_expression"] = aws.StringValue(v) + m["schedule_expression"] = aws.ToString(v) } return []interface{}{m} diff --git a/internal/service/secretsmanager/secret_rotation_test.go b/internal/service/secretsmanager/secret_rotation_test.go index d4e7de859b3..abff0faf2e4 100644 --- a/internal/service/secretsmanager/secret_rotation_test.go +++ b/internal/service/secretsmanager/secret_rotation_test.go @@ -9,8 +9,8 @@ import ( "strconv" "testing" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -25,9 +25,12 @@ func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { ctx := acctest.Context(t) var secret secretsmanager.DescribeSecretOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_secretsmanager_secret_rotation.test" - lambdaFunctionResourceName := "aws_lambda_function.test" - days := 7 + const ( + resourceName = "aws_secretsmanager_secret_rotation.test" + lambdaFunctionResourceName = "aws_lambda_function.test" + days = 7 + ) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), @@ -36,7 +39,7 @@ func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccSecretRotationConfig_basic(rName, days), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckSecretRotationExists(ctx, resourceName, &secret), resource.TestCheckResourceAttr(resourceName, "rotation_enabled", "true"), resource.TestCheckResourceAttrPair(resourceName, "rotation_lambda_arn", lambdaFunctionResourceName, "arn"), @@ -55,14 +58,72 @@ func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { }) } +func TestAccSecretsManagerSecretRotation_disappears(t *testing.T) { + ctx := acctest.Context(t) + var secret secretsmanager.DescribeSecretOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + const ( + resourceName = "aws_secretsmanager_secret_rotation.test" + days = 7 + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretRotationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretRotationConfig_basic(rName, days), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretRotationExists(ctx, resourceName, &secret), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsecretsmanager.ResourceSecretRotation(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccSecretsManagerSecretRotation_Disappears_secret(t *testing.T) { + ctx := acctest.Context(t) + var secret secretsmanager.DescribeSecretOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + const ( + resourceName = "aws_secretsmanager_secret_rotation.test" + secretResourceName = "aws_secretsmanager_secret.test" + days = 7 + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretRotationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretRotationConfig_basic(rName, days), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretRotationExists(ctx, resourceName, &secret), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsecretsmanager.ResourceSecret(), secretResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccSecretsManagerSecretRotation_scheduleExpression(t *testing.T) { ctx := acctest.Context(t) var secret secretsmanager.DescribeSecretOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_secretsmanager_secret_rotation.test" - lambdaFunctionResourceName := "aws_lambda_function.test" - scheduleExpression := "rate(10 days)" - scheduleExpression02 := "rate(10 days)" + const ( + resourceName = "aws_secretsmanager_secret_rotation.test" + lambdaFunctionResourceName = "aws_lambda_function.test" + scheduleExpression = "rate(10 days)" + scheduleExpression02 = "rate(10 days)" + ) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), @@ -108,6 +169,7 @@ func TestAccSecretsManagerSecretRotation_scheduleExpressionToDays(t *testing.T) scheduleExpression = "rate(10 days)" days = 7 ) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), @@ -149,10 +211,13 @@ func TestAccSecretsManagerSecretRotation_scheduleExpressionHours(t *testing.T) { ctx := acctest.Context(t) var secret secretsmanager.DescribeSecretOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_secretsmanager_secret_rotation.test" - lambdaFunctionResourceName := "aws_lambda_function.test" - scheduleExpression := "rate(6 hours)" - scheduleExpression02 := "rate(10 hours)" + const ( + resourceName = "aws_secretsmanager_secret_rotation.test" + lambdaFunctionResourceName = "aws_lambda_function.test" + scheduleExpression = "rate(6 hours)" + scheduleExpression02 = "rate(10 hours)" + ) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), @@ -193,10 +258,12 @@ func TestAccSecretsManagerSecretRotation_duration(t *testing.T) { ctx := acctest.Context(t) var secret secretsmanager.DescribeSecretOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_secretsmanager_secret_rotation.test" - lambdaFunctionResourceName := "aws_lambda_function.test" - days := 7 - duration := "3h" + const ( + resourceName = "aws_secretsmanager_secret_rotation.test" + lambdaFunctionResourceName = "aws_lambda_function.test" + days = 7 + duration = "3h" + ) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, @@ -243,11 +310,11 @@ func testAccCheckSecretRotationDestroy(ctx context.Context) resource.TestCheckFu return err } - if !aws.BoolValue(output.RotationEnabled) { + if !aws.ToBool(output.RotationEnabled) { continue } - return fmt.Errorf("Secrets Manager Secret %s rotation still enabled", rs.Primary.ID) + return fmt.Errorf("Secrets Manager Secret Rotation %s still enabled", rs.Primary.ID) } return nil @@ -261,10 +328,6 @@ func testAccCheckSecretRotationExists(ctx context.Context, n string, v *secretsm return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Secrets Manager Secret Rotation ID is set") - } - conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) output, err := tfsecretsmanager.FindSecretByID(ctx, conn, rs.Primary.ID) @@ -273,8 +336,8 @@ func testAccCheckSecretRotationExists(ctx context.Context, n string, v *secretsm return err } - if !aws.BoolValue(output.RotationEnabled) { - return fmt.Errorf("Secrets Manager Secret %s rotation not enabled", rs.Primary.ID) + if !aws.ToBool(output.RotationEnabled) { + return fmt.Errorf("Secrets Manager Secret Rotation %s not enabled", rs.Primary.ID) } *v = *output @@ -316,7 +379,7 @@ func testSecretValueIsCurrent(ctx context.Context, rName string) resource.TestCh } } -func testAccSecretRotationConfigBase(rName string) string { +func testAccSecretRotationConfig_base(rName string) string { return fmt.Sprintf(` # Not a real rotation function resource "aws_lambda_function" "test" { @@ -339,7 +402,7 @@ resource "aws_lambda_permission" "test" { func testAccSecretRotationConfig_basic(rName string, automaticallyAfterDays int) string { return acctest.ConfigCompose( acctest.ConfigLambdaBase(rName, rName, rName), - testAccSecretRotationConfigBase(rName), + testAccSecretRotationConfig_base(rName), fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { name = %[1]q @@ -366,7 +429,7 @@ resource "aws_secretsmanager_secret_rotation" "test" { func testAccSecretRotationConfig_scheduleExpression(rName string, scheduleExpression string) string { return acctest.ConfigCompose( acctest.ConfigLambdaBase(rName, rName, rName), - testAccSecretRotationConfigBase(rName), + testAccSecretRotationConfig_base(rName), fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { name = %[1]q @@ -388,7 +451,7 @@ resource "aws_secretsmanager_secret_rotation" "test" { func testAccSecretRotationConfig_duration(rName string, automaticallyAfterDays int, duration string) string { return acctest.ConfigCompose( acctest.ConfigLambdaBase(rName, rName, rName), - testAccSecretRotationConfigBase(rName), + testAccSecretRotationConfig_base(rName), fmt.Sprintf(` resource "aws_secretsmanager_secret" "test" { name = %[1]q diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index 7efefd82aed..6146f41a575 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -67,8 +67,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka Name: "Secret Policy", }, { - Factory: ResourceSecretRotation, + Factory: resourceSecretRotation, TypeName: "aws_secretsmanager_secret_rotation", + Name: "Secret Rotation", }, { Factory: resourceSecretVersion, From de602c12d7a6143f155c9539a473deffe8481f31 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 11:24:00 -0500 Subject: [PATCH 27/35] d/aws_secretsmanager_secret_rotation: Tidy up. --- .../secretsmanager/secret_rotation_data_source.go | 14 ++++++-------- .../service/secretsmanager/service_package_gen.go | 3 ++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/internal/service/secretsmanager/secret_rotation_data_source.go b/internal/service/secretsmanager/secret_rotation_data_source.go index 449b1cb4e63..05bd8551ff7 100644 --- a/internal/service/secretsmanager/secret_rotation_data_source.go +++ b/internal/service/secretsmanager/secret_rotation_data_source.go @@ -6,16 +6,15 @@ package secretsmanager import ( "context" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" ) -// @SDKDataSource("aws_secretsmanager_secret_rotation") -func DataSourceSecretRotation() *schema.Resource { +// @SDKDataSource("aws_secretsmanager_secret_rotation", name="Secret Rotation") +func dataSourceSecretRotation() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceSecretRotationRead, @@ -49,9 +48,8 @@ func DataSourceSecretRotation() *schema.Resource { }, }, "secret_id": { - Type: schema.TypeString, - ValidateFunc: validation.StringLenBetween(1, 2048), - Required: true, + Type: schema.TypeString, + Required: true, }, }, } @@ -68,7 +66,7 @@ func dataSourceSecretRotationRead(ctx context.Context, d *schema.ResourceData, m return sdkdiag.AppendErrorf(diags, "reading Secrets Manager Secret (%s): %s", secretID, err) } - d.SetId(aws.StringValue(output.ARN)) + d.SetId(aws.ToString(output.ARN)) d.Set("rotation_enabled", output.RotationEnabled) d.Set("rotation_lambda_arn", output.RotationLambdaARN) if err := d.Set("rotation_rules", flattenRotationRules(output.RotationRules)); err != nil { diff --git a/internal/service/secretsmanager/service_package_gen.go b/internal/service/secretsmanager/service_package_gen.go index 6146f41a575..2996b7e9477 100644 --- a/internal/service/secretsmanager/service_package_gen.go +++ b/internal/service/secretsmanager/service_package_gen.go @@ -35,8 +35,9 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac Name: "Secret", }, { - Factory: DataSourceSecretRotation, + Factory: dataSourceSecretRotation, TypeName: "aws_secretsmanager_secret_rotation", + Name: "Secret Rotation", }, { Factory: dataSourceSecretVersion, From 18f7aea238663f478b557cc6cc4358ec6ecf6ee9 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 11:34:09 -0500 Subject: [PATCH 28/35] secretsmanager: Tidy up sweepers. --- internal/service/secretsmanager/sweep.go | 102 ++++++++++------------- 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/internal/service/secretsmanager/sweep.go b/internal/service/secretsmanager/sweep.go index 9393ef8097f..4239d0d5de8 100644 --- a/internal/service/secretsmanager/sweep.go +++ b/internal/service/secretsmanager/sweep.go @@ -7,9 +7,8 @@ import ( "fmt" "log" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/aws/aws-sdk-go/aws" - "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" @@ -34,42 +33,37 @@ func sweepSecretPolicies(region string) error { return fmt.Errorf("error getting client: %s", err) } conn := client.SecretsManagerClient(ctx) + input := &secretsmanager.ListSecretsInput{} + sweepResources := make([]sweep.Sweepable, 0) - paginator := secretsmanager.NewListSecretsPaginator(conn, &secretsmanager.ListSecretsInput{}) + paginator := secretsmanager.NewListSecretsPaginator(conn, input) for paginator.HasMorePages() { page, err := paginator.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Secrets Manager Secret Policy sweep for %s: %s", region, err) + return nil + } + if err != nil { - if awsv2.SkipSweepError(err) { - log.Printf("[WARN] Skipping Secrets Manager Secret sweep for %s: %s", region, err) - return nil - } - return fmt.Errorf("error retrieving Secrets Manager Secrets: %w", err) + return fmt.Errorf("error listing Secrets Manager Secrets (%s): %w", region, err) } - if page != nil { - if len(page.SecretList) == 0 { - log.Print("[DEBUG] No Secrets Manager Secrets to sweep") - } - - for _, secret := range page.SecretList { - name := aws.StringValue(secret.Name) - - log.Printf("[INFO] Deleting Secrets Manager Secret Policy: %s", name) - input := &secretsmanager.DeleteResourcePolicyInput{ - SecretId: aws.String(name), - } - - _, err := conn.DeleteResourcePolicy(ctx, input) - if err != nil { - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - continue - } - log.Printf("[ERROR] Failed to delete Secrets Manager Secret Policy (%s): %s", name, err) - } - } + for _, v := range page.SecretList { + r := resourceSecretPolicy() + d := r.Data(nil) + d.SetId(aws.ToString(v.ARN)) + + sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } } + err = sweep.SweepOrchestrator(ctx, sweepResources) + + if err != nil { + return fmt.Errorf("error sweeping Secrets Manager Secret Policies (%s): %w", region, err) + } + return nil } @@ -80,41 +74,35 @@ func sweepSecrets(region string) error { return fmt.Errorf("error getting client: %s", err) } conn := client.SecretsManagerClient(ctx) + input := &secretsmanager.ListSecretsInput{} + sweepResources := make([]sweep.Sweepable, 0) - paginator := secretsmanager.NewListSecretsPaginator(conn, &secretsmanager.ListSecretsInput{}) + paginator := secretsmanager.NewListSecretsPaginator(conn, input) for paginator.HasMorePages() { page, err := paginator.NextPage(ctx) + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Secrets Manager Secret sweep for %s: %s", region, err) + return nil + } + if err != nil { - if awsv2.SkipSweepError(err) { - log.Printf("[WARN] Skipping Secrets Manager Secret sweep for %s: %s", region, err) - return nil - } - return fmt.Errorf("error retrieving Secrets Manager Secrets: %w", err) + return fmt.Errorf("error listing Secrets Manager Secrets (%s): %w", region, err) } - if page != nil { - if len(page.SecretList) == 0 { - log.Print("[DEBUG] No Secrets Manager Secrets to sweep") - } - - for _, secret := range page.SecretList { - name := aws.StringValue(secret.Name) - - log.Printf("[INFO] Deleting Secrets Manager Secret: %s", name) - input := &secretsmanager.DeleteSecretInput{ - ForceDeleteWithoutRecovery: aws.Bool(true), - SecretId: aws.String(name), - } - - _, err := conn.DeleteSecret(ctx, input) - if err != nil { - if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { - continue - } - log.Printf("[ERROR] Failed to delete Secrets Manager Secret (%s): %s", name, err) - } - } + for _, v := range page.SecretList { + r := resourceSecret() + d := r.Data(nil) + d.SetId(aws.ToString(v.ARN)) + + sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } } + + err = sweep.SweepOrchestrator(ctx, sweepResources) + + if err != nil { + return fmt.Errorf("error sweeping Secrets Manager Secrets (%s): %w", region, err) + } + return nil } From 16b5fd780c0e9ec490660940e400b66d8e13ede7 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 11:50:36 -0500 Subject: [PATCH 29/35] secretsmanager: Tidy up sweepers. --- internal/service/secretsmanager/sweep.go | 27 ++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/internal/service/secretsmanager/sweep.go b/internal/service/secretsmanager/sweep.go index 4239d0d5de8..6024431cb4c 100644 --- a/internal/service/secretsmanager/sweep.go +++ b/internal/service/secretsmanager/sweep.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/sdk" ) func RegisterSweepers() { @@ -50,9 +51,16 @@ func sweepSecretPolicies(region string) error { } for _, v := range page.SecretList { + arn := aws.ToString(v.ARN) + + if owningService := aws.ToString(v.OwningService); owningService != "" { + log.Printf("[INFO] Skipping Secrets Manager Secret %s: OwningService=%s", arn, owningService) + continue + } + r := resourceSecretPolicy() d := r.Data(nil) - d.SetId(aws.ToString(v.ARN)) + d.SetId(arn) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } @@ -90,9 +98,24 @@ func sweepSecrets(region string) error { } for _, v := range page.SecretList { + arn := aws.ToString(v.ARN) + + if owningService := aws.ToString(v.OwningService); owningService != "" { + log.Printf("[INFO] Skipping Secrets Manager Secret %s: OwningService=%s", arn, owningService) + continue + } + r := resourceSecret() d := r.Data(nil) - d.SetId(aws.ToString(v.ARN)) + d.SetId(arn) + // Refresh replicas. + if err := sdk.ReadResource(ctx, r, d, client); err != nil { + log.Printf("[WARN] Skipping Secrets Manager Secret %s: %s", arn, err) + continue + } + if d.Id() == "" { + continue + } sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } From 04bd5ac688ef35cb1000b0dc79eebcd1dbfa7165 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 12:15:28 -0500 Subject: [PATCH 30/35] Remove unused code. --- internal/service/secretsmanager/errors.go | 14 -------------- internal/service/secretsmanager/exports_test.go | 3 --- 2 files changed, 17 deletions(-) delete mode 100644 internal/service/secretsmanager/errors.go diff --git a/internal/service/secretsmanager/errors.go b/internal/service/secretsmanager/errors.go deleted file mode 100644 index 5d8be3cca74..00000000000 --- a/internal/service/secretsmanager/errors.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package secretsmanager - -import ( - "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" -) - -var ( - errCodeMalformedPolicyDocumentException = (*types.MalformedPolicyDocumentException)(nil).ErrorCode() - errCodeResourceNotFoundException = (*types.ResourceNotFoundException)(nil).ErrorCode() - errCodeInvalidRequestException = (*types.InvalidRequestException)(nil).ErrorCode() -) diff --git a/internal/service/secretsmanager/exports_test.go b/internal/service/secretsmanager/exports_test.go index 642c210b254..4577a9d76ce 100644 --- a/internal/service/secretsmanager/exports_test.go +++ b/internal/service/secretsmanager/exports_test.go @@ -13,7 +13,4 @@ var ( FindSecretByID = findSecretByID FindSecretPolicyByID = findSecretPolicyByID FindSecretVersionByTwoPartKey = findSecretVersionByTwoPartKey - - ErrCodeResourceNotFoundException = errCodeResourceNotFoundException - ErrCodeInvalidRequestException = errCodeInvalidRequestException ) From a13e9c99fd4598051395a32a6208537c1e6c36aa Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 12:24:18 -0500 Subject: [PATCH 31/35] Add (and comment out) 'TestAccSecretsManagerSecretVersion_multipleVersions'. --- .../secretsmanager/secret_version_test.go | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/internal/service/secretsmanager/secret_version_test.go b/internal/service/secretsmanager/secret_version_test.go index e9199d74488..e7108f0ac81 100644 --- a/internal/service/secretsmanager/secret_version_test.go +++ b/internal/service/secretsmanager/secret_version_test.go @@ -156,7 +156,7 @@ func TestAccSecretsManagerSecretVersion_disappears(t *testing.T) { testAccCheckSecretVersionExists(ctx, resourceName, &version), acctest.CheckResourceDisappears(ctx, acctest.Provider, tfsecretsmanager.ResourceSecretVersion(), resourceName), ), - // Because resource Delete leaves a secret with a single stage ("AWSCURRENT"), the resource is still there. + // Because resource Delete leaves a secret version with a single stage ("AWSCURRENT"), the resource is still there. // ExpectNonEmptyPlan: true, }, }, @@ -188,6 +188,44 @@ func TestAccSecretsManagerSecretVersion_Disappears_secret(t *testing.T) { }) } +/* + + Need to handle 'AWSPREVIOUS' better. + +func TestAccSecretsManagerSecretVersion_multipleVersions(t *testing.T) { + ctx := acctest.Context(t) + var version1, version2, version3 secretsmanager.GetSecretValueOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resource1Name := "aws_secretsmanager_secret_version.test1" + resource2Name := "aws_secretsmanager_secret_version.test2" + resource3Name := "aws_secretsmanager_secret_version.test3" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckSecretVersionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccSecretVersionConfig_multipleVersions(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretVersionExists(ctx, resource1Name, &version1), + resource.TestCheckResourceAttr(resource1Name, "version_stages.#", "1"), + resource.TestCheckTypeSetElemAttr(resource1Name, "version_stages.*", "one"), + testAccCheckSecretVersionExists(ctx, resource1Name, &version2), + resource.TestCheckResourceAttr(resource2Name, "version_stages.#", "2"), + resource.TestCheckTypeSetElemAttr(resource2Name, "version_stages.*", "two"), + resource.TestCheckTypeSetElemAttr(resource2Name, "version_stages.*", "AWSCURRENT"), + testAccCheckSecretVersionExists(ctx, resource1Name, &version3), + resource.TestCheckResourceAttr(resource3Name, "version_stages.#", "1"), + resource.TestCheckTypeSetElemAttr(resource3Name, "version_stages.*", "three"), + ), + }, + }, + }) +} +*/ + func testAccCheckSecretVersionDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).SecretsManagerClient(ctx) @@ -309,3 +347,34 @@ resource "aws_secretsmanager_secret_version" "test" { } `, rName) } + +/* +func testAccSecretVersionConfig_multipleVersions(rName string) string { + return fmt.Sprintf(` +resource "aws_secretsmanager_secret" "test" { + name = %[1]q +} + +resource "aws_secretsmanager_secret_version" "test1" { + secret_id = aws_secretsmanager_secret.test.id + secret_string = "test1" + + version_stages = ["one"] +} + +resource "aws_secretsmanager_secret_version" "test2" { + secret_id = aws_secretsmanager_secret.test.id + secret_string = "test2" + + version_stages = ["two", "AWSCURRENT"] +} + +resource "aws_secretsmanager_secret_version" "test3" { + secret_id = aws_secretsmanager_secret.test.id + secret_string = "test3" + + version_stages = ["three"] +} +`, rName) +} +*/ From 18e734b355ed5dcf5644f73231968736fd454148 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 14:31:00 -0500 Subject: [PATCH 32/35] Add CHANGELOG entries. --- .changelog/35117.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/35117.txt diff --git a/.changelog/35117.txt b/.changelog/35117.txt new file mode 100644 index 00000000000..9dff1f8c89e --- /dev/null +++ b/.changelog/35117.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +data-source/aws_secretsmanager_secret: Add `created_date` and `last_changed_date` attributes +``` + +```release-note:enhancement +data-source/aws_secretsmanager_secret_version: Add `created_date` attribute +``` \ No newline at end of file From c700959fb92fd44a0daae569c49bfd2c038db5cb Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 14:55:51 -0500 Subject: [PATCH 33/35] r/aws_secretsmanager_secret_rotation: Add state migrater for 'rotate_immediately'. --- .../service/secretsmanager/secret_rotation.go | 3 ++ .../secretsmanager/secret_rotation_migrate.go | 29 ++++++++++++++ .../secretsmanager/secret_rotation_test.go | 39 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 internal/service/secretsmanager/secret_rotation_migrate.go diff --git a/internal/service/secretsmanager/secret_rotation.go b/internal/service/secretsmanager/secret_rotation.go index aa53fc36462..ebc36ae2531 100644 --- a/internal/service/secretsmanager/secret_rotation.go +++ b/internal/service/secretsmanager/secret_rotation.go @@ -34,6 +34,9 @@ func resourceSecretRotation() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, + MigrateState: secretRotationMigrateState, + SchemaVersion: 1, + Schema: map[string]*schema.Schema{ "rotate_immediately": { Type: schema.TypeBool, diff --git a/internal/service/secretsmanager/secret_rotation_migrate.go b/internal/service/secretsmanager/secret_rotation_migrate.go new file mode 100644 index 00000000000..42c622aba8a --- /dev/null +++ b/internal/service/secretsmanager/secret_rotation_migrate.go @@ -0,0 +1,29 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package secretsmanager + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func secretRotationMigrateState(v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { + switch v { + case 0: + return migrateSecretRotationStateV0toV1(is) + default: + return is, fmt.Errorf("Unexpected schema version: %d", v) + } +} + +func migrateSecretRotationStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) { + if is.Empty() { + return is, nil + } + + is.Attributes["rotate_immediately"] = "true" + + return is, nil +} diff --git a/internal/service/secretsmanager/secret_rotation_test.go b/internal/service/secretsmanager/secret_rotation_test.go index bd132aac8c1..0258616c730 100644 --- a/internal/service/secretsmanager/secret_rotation_test.go +++ b/internal/service/secretsmanager/secret_rotation_test.go @@ -60,6 +60,45 @@ func TestAccSecretsManagerSecretRotation_basic(t *testing.T) { }) } +func TestAccSecretsManagerSecretRotation_upgradePreRotateImmediately(t *testing.T) { + ctx := acctest.Context(t) + var secret secretsmanager.DescribeSecretOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + const ( + resourceName = "aws_secretsmanager_secret_rotation.test" + days = 7 + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerEndpointID), + CheckDestroy: testAccCheckSecretRotationDestroy(ctx), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "5.32.0", + }, + }, + Config: testAccSecretRotationConfig_basic(rName, days), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretRotationExists(ctx, resourceName, &secret), + resource.TestCheckNoResourceAttr(resourceName, "rotate_immediately"), + ), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Config: testAccSecretRotationConfig_basic(rName, days), + Check: resource.ComposeTestCheckFunc( + testAccCheckSecretRotationExists(ctx, resourceName, &secret), + resource.TestCheckResourceAttr(resourceName, "rotate_immediately", "true"), + ), + }, + }, + }) +} + func TestAccSecretsManagerSecretRotation_rotateImmediately(t *testing.T) { ctx := acctest.Context(t) var secret secretsmanager.DescribeSecretOutput From 5feea78c8e603c2aad45a9c40a2cc4f98a906ef1 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 15:33:33 -0500 Subject: [PATCH 34/35] r/aws_secretsmanager_secret_rotation: Use StateUpgraders. --- .../service/secretsmanager/secret_rotation.go | 8 ++- .../secretsmanager/secret_rotation_migrate.go | 60 ++++++++++++++----- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/internal/service/secretsmanager/secret_rotation.go b/internal/service/secretsmanager/secret_rotation.go index ebc36ae2531..1faeb4e3b25 100644 --- a/internal/service/secretsmanager/secret_rotation.go +++ b/internal/service/secretsmanager/secret_rotation.go @@ -34,8 +34,14 @@ func resourceSecretRotation() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, - MigrateState: secretRotationMigrateState, SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: secretRotationResourceV0().CoreConfigSchema().ImpliedType(), + Upgrade: secretRotationStateUpgradeV0, + Version: 0, + }, + }, Schema: map[string]*schema.Schema{ "rotate_immediately": { diff --git a/internal/service/secretsmanager/secret_rotation_migrate.go b/internal/service/secretsmanager/secret_rotation_migrate.go index 42c622aba8a..7a498f12c8d 100644 --- a/internal/service/secretsmanager/secret_rotation_migrate.go +++ b/internal/service/secretsmanager/secret_rotation_migrate.go @@ -4,26 +4,56 @@ package secretsmanager import ( - "fmt" + "context" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func secretRotationMigrateState(v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { - switch v { - case 0: - return migrateSecretRotationStateV0toV1(is) - default: - return is, fmt.Errorf("Unexpected schema version: %d", v) +func secretRotationStateUpgradeV0(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + if v, ok := rawState["rotate_immediately"]; !ok || v == nil { + rawState["rotate_immediately"] = "true" } + + return rawState, nil } -func migrateSecretRotationStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) { - if is.Empty() { - return is, nil +func secretRotationResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rotation_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "rotation_lambda_arn": { + Type: schema.TypeString, + Optional: true, + }, + "rotation_rules": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "automatically_after_days": { + Type: schema.TypeInt, + Optional: true, + }, + "duration": { + Type: schema.TypeString, + Optional: true, + }, + "schedule_expression": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "secret_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, } - - is.Attributes["rotate_immediately"] = "true" - - return is, nil } From 26da4d3e191a2ab7ed6e26ac4618a548aaac496e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 12 Jan 2024 15:35:46 -0500 Subject: [PATCH 35/35] d/aws_secretsmagare_secret: Fix acceptance test check. --- internal/service/secretsmanager/secret_data_source_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/service/secretsmanager/secret_data_source_test.go b/internal/service/secretsmanager/secret_data_source_test.go index 1417ea625d0..4c2cf44c516 100644 --- a/internal/service/secretsmanager/secret_data_source_test.go +++ b/internal/service/secretsmanager/secret_data_source_test.go @@ -120,8 +120,6 @@ func testAccSecretCheckDataSource(datasourceName, resourceName string) resource. "name", "policy", "tags.#", - "created_date", - "last_changed_date", } for _, attrName := range attrNames {