From af8a19e76c99490be734e73c048852c4dc6c7f68 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 15:01:12 +0200 Subject: [PATCH 01/14] feat: regenerate `v2` client --- internal/conns/awsclient_gen.go | 5 -- .../service/redshiftserverless/generate.go | 2 +- .../service_endpoint_resolver_gen.go | 64 ------------------- .../service_endpoints_gen_test.go | 43 ++----------- .../redshiftserverless/service_package_gen.go | 22 ------- .../service/redshiftserverless/tags_gen.go | 36 +++++------ names/data/names_data.hcl | 2 +- 7 files changed, 27 insertions(+), 147 deletions(-) diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index 3365127958a2..1f2cc536ab42 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -243,7 +243,6 @@ import ( quicksight_sdkv1 "github.com/aws/aws-sdk-go/service/quicksight" rds_sdkv1 "github.com/aws/aws-sdk-go/service/rds" redshift_sdkv1 "github.com/aws/aws-sdk-go/service/redshift" - redshiftserverless_sdkv1 "github.com/aws/aws-sdk-go/service/redshiftserverless" route53resolver_sdkv1 "github.com/aws/aws-sdk-go/service/route53resolver" sagemaker_sdkv1 "github.com/aws/aws-sdk-go/service/sagemaker" simpledb_sdkv1 "github.com/aws/aws-sdk-go/service/simpledb" @@ -988,10 +987,6 @@ func (c *AWSClient) RedshiftDataClient(ctx context.Context) *redshiftdata_sdkv2. return errs.Must(client[*redshiftdata_sdkv2.Client](ctx, c, names.RedshiftData, make(map[string]any))) } -func (c *AWSClient) RedshiftServerlessConn(ctx context.Context) *redshiftserverless_sdkv1.RedshiftServerless { - return errs.Must(conn[*redshiftserverless_sdkv1.RedshiftServerless](ctx, c, names.RedshiftServerless, make(map[string]any))) -} - func (c *AWSClient) RedshiftServerlessClient(ctx context.Context) *redshiftserverless_sdkv2.Client { return errs.Must(client[*redshiftserverless_sdkv2.Client](ctx, c, names.RedshiftServerless, make(map[string]any))) } diff --git a/internal/service/redshiftserverless/generate.go b/internal/service/redshiftserverless/generate.go index 47d2b4c39b3a..df71dd690fb5 100644 --- a/internal/service/redshiftserverless/generate.go +++ b/internal/service/redshiftserverless/generate.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/tags/main.go -ListTags -ServiceTagsSlice -UpdateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTags -ServiceTagsSlice -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/redshiftserverless/service_endpoint_resolver_gen.go b/internal/service/redshiftserverless/service_endpoint_resolver_gen.go index a9f40a001da8..f5aab0139b87 100644 --- a/internal/service/redshiftserverless/service_endpoint_resolver_gen.go +++ b/internal/service/redshiftserverless/service_endpoint_resolver_gen.go @@ -6,78 +6,14 @@ import ( "context" "fmt" "net" - "net/url" aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" redshiftserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" smithyendpoints "github.com/aws/smithy-go/endpoints" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/errs" ) -var _ endpoints_sdkv1.Resolver = resolverSDKv1{} - -type resolverSDKv1 struct { - ctx context.Context -} - -func newEndpointResolverSDKv1(ctx context.Context) resolverSDKv1 { - return resolverSDKv1{ - ctx: ctx, - } -} - -func (r resolverSDKv1) EndpointFor(service, region string, opts ...func(*endpoints_sdkv1.Options)) (endpoint endpoints_sdkv1.ResolvedEndpoint, err error) { - ctx := r.ctx - - var opt endpoints_sdkv1.Options - opt.Set(opts...) - - useFIPS := opt.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled - - defaultResolver := endpoints_sdkv1.DefaultResolver() - - if useFIPS { - ctx = tflog.SetField(ctx, "tf_aws.use_fips", useFIPS) - - endpoint, err = defaultResolver.EndpointFor(service, region, opts...) - if err != nil { - return endpoint, err - } - - tflog.Debug(ctx, "endpoint resolved", map[string]any{ - "tf_aws.endpoint": endpoint.URL, - }) - - var endpointURL *url.URL - endpointURL, err = url.Parse(endpoint.URL) - if err != nil { - return endpoint, err - } - - hostname := endpointURL.Hostname() - _, err = net.LookupHost(hostname) - if err != nil { - if dnsErr, ok := errs.As[*net.DNSError](err); ok && dnsErr.IsNotFound { - tflog.Debug(ctx, "default endpoint host not found, disabling FIPS", map[string]any{ - "tf_aws.hostname": hostname, - }) - opts = append(opts, func(o *endpoints_sdkv1.Options) { - o.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled - }) - } else { - err = fmt.Errorf("looking up accessanalyzer endpoint %q: %s", hostname, err) - return - } - } else { - return endpoint, err - } - } - - return defaultResolver.EndpointFor(service, region, opts...) -} - var _ redshiftserverless_sdkv2.EndpointResolverV2 = resolverSDKv2{} type resolverSDKv2 struct { diff --git a/internal/service/redshiftserverless/service_endpoints_gen_test.go b/internal/service/redshiftserverless/service_endpoints_gen_test.go index fc4ca9899a79..4031ac2bb0ee 100644 --- a/internal/service/redshiftserverless/service_endpoints_gen_test.go +++ b/internal/service/redshiftserverless/service_endpoints_gen_test.go @@ -18,8 +18,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" redshiftserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - redshiftserverless_sdkv1 "github.com/aws/aws-sdk-go/service/redshiftserverless" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" "github.com/google/go-cmp/cmp" @@ -236,25 +234,13 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S }, } - t.Run("v1", func(t *testing.T) { - for name, testcase := range testcases { //nolint:paralleltest // uses t.Setenv - testcase := testcase + for name, testcase := range testcases { //nolint:paralleltest // uses t.Setenv + testcase := testcase - t.Run(name, func(t *testing.T) { - testEndpointCase(t, providerRegion, testcase, callServiceV1) - }) - } - }) - - t.Run("v2", func(t *testing.T) { - for name, testcase := range testcases { //nolint:paralleltest // uses t.Setenv - testcase := testcase - - t.Run(name, func(t *testing.T) { - testEndpointCase(t, providerRegion, testcase, callServiceV2) - }) - } - }) + t.Run(name, func(t *testing.T) { + testEndpointCase(t, providerRegion, testcase, callService) + }) + } } func defaultEndpoint(region string) (url.URL, error) { @@ -292,7 +278,7 @@ func defaultFIPSEndpoint(region string) (url.URL, error) { return ep.URI, nil } -func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { +func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { t.Helper() client := meta.RedshiftServerlessClient(ctx) @@ -317,21 +303,6 @@ func callServiceV2(ctx context.Context, t *testing.T, meta *conns.AWSClient) api return result } -func callServiceV1(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { - t.Helper() - - client := meta.RedshiftServerlessConn(ctx) - - req, _ := client.ListNamespacesRequest(&redshiftserverless_sdkv1.ListNamespacesInput{}) - - req.HTTPRequest.URL.Path = "/" - - return apiCallParams{ - endpoint: req.HTTPRequest.URL.String(), - region: aws_sdkv1.StringValue(client.Config.Region), - } -} - func withNoConfig(_ *caseSetup) { // no-op } diff --git a/internal/service/redshiftserverless/service_package_gen.go b/internal/service/redshiftserverless/service_package_gen.go index 6cc966080227..0ef2fd6e08b6 100644 --- a/internal/service/redshiftserverless/service_package_gen.go +++ b/internal/service/redshiftserverless/service_package_gen.go @@ -7,10 +7,6 @@ import ( aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" redshiftserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - redshiftserverless_sdkv1 "github.com/aws/aws-sdk-go/service/redshiftserverless" - "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -96,24 +92,6 @@ func (p *servicePackage) ServicePackageName() string { return names.RedshiftServerless } -// 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) (*redshiftserverless_sdkv1.RedshiftServerless, error) { - sess := config[names.AttrSession].(*session_sdkv1.Session) - - cfg := aws_sdkv1.Config{} - - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - cfg.Endpoint = aws_sdkv1.String(endpoint) - } else { - cfg.EndpointResolver = newEndpointResolverSDKv1(ctx) - } - - return redshiftserverless_sdkv1.New(sess.Copy(&cfg)), nil -} - // 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) (*redshiftserverless_sdkv2.Client, error) { cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) diff --git a/internal/service/redshiftserverless/tags_gen.go b/internal/service/redshiftserverless/tags_gen.go index 89fce014c350..b8817ca2788e 100644 --- a/internal/service/redshiftserverless/tags_gen.go +++ b/internal/service/redshiftserverless/tags_gen.go @@ -5,9 +5,9 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "github.com/aws/aws-sdk-go/service/redshiftserverless/redshiftserverlessiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" + awstypes "github.com/aws/aws-sdk-go-v2/service/redshiftserverless/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,12 +19,12 @@ import ( // listTags lists redshiftserverless service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func listTags(ctx context.Context, conn redshiftserverlessiface.RedshiftServerlessAPI, identifier string) (tftags.KeyValueTags, error) { +func listTags(ctx context.Context, conn *redshiftserverless.Client, identifier string, optFns ...func(*redshiftserverless.Options)) (tftags.KeyValueTags, error) { input := &redshiftserverless.ListTagsForResourceInput{ ResourceArn: aws.String(identifier), } - output, err := conn.ListTagsForResourceWithContext(ctx, input) + output, err := conn.ListTagsForResource(ctx, input, optFns...) if err != nil { return tftags.New(ctx, nil), err @@ -36,7 +36,7 @@ func listTags(ctx context.Context, conn redshiftserverlessiface.RedshiftServerle // ListTags lists redshiftserverless service tags and set them in Context. // It is called from outside this package. func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { - tags, err := listTags(ctx, meta.(*conns.AWSClient).RedshiftServerlessConn(ctx), identifier) + tags, err := listTags(ctx, meta.(*conns.AWSClient).RedshiftServerlessClient(ctx), identifier) if err != nil { return err @@ -52,11 +52,11 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier stri // []*SERVICE.Tag handling // Tags returns redshiftserverless service tags. -func Tags(tags tftags.KeyValueTags) []*redshiftserverless.Tag { - result := make([]*redshiftserverless.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 := &redshiftserverless.Tag{ + tag := awstypes.Tag{ Key: aws.String(k), Value: aws.String(v), } @@ -68,11 +68,11 @@ func Tags(tags tftags.KeyValueTags) []*redshiftserverless.Tag { } // KeyValueTags creates tftags.KeyValueTags from redshiftserverless service tags. -func KeyValueTags(ctx context.Context, tags []*redshiftserverless.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) @@ -80,7 +80,7 @@ func KeyValueTags(ctx context.Context, tags []*redshiftserverless.Tag) tftags.Ke // getTagsIn returns redshiftserverless service tags from Context. // nil is returned if there are no input tags. -func getTagsIn(ctx context.Context) []*redshiftserverless.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 @@ -91,7 +91,7 @@ func getTagsIn(ctx context.Context) []*redshiftserverless.Tag { } // setTagsOut sets redshiftserverless service tags in Context. -func setTagsOut(ctx context.Context, tags []*redshiftserverless.Tag) { +func setTagsOut(ctx context.Context, tags []awstypes.Tag) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = option.Some(KeyValueTags(ctx, tags)) } @@ -100,7 +100,7 @@ func setTagsOut(ctx context.Context, tags []*redshiftserverless.Tag) { // updateTags updates redshiftserverless 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 redshiftserverlessiface.RedshiftServerlessAPI, identifier string, oldTagsMap, newTagsMap any) error { +func updateTags(ctx context.Context, conn *redshiftserverless.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*redshiftserverless.Options)) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -111,10 +111,10 @@ func updateTags(ctx context.Context, conn redshiftserverlessiface.RedshiftServer if len(removedTags) > 0 { input := &redshiftserverless.UntagResourceInput{ ResourceArn: 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) @@ -129,7 +129,7 @@ func updateTags(ctx context.Context, conn redshiftserverlessiface.RedshiftServer 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) @@ -142,5 +142,5 @@ func updateTags(ctx context.Context, conn redshiftserverlessiface.RedshiftServer // UpdateTags updates redshiftserverless 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).RedshiftServerlessConn(ctx), identifier, oldTags, newTags) + return updateTags(ctx, meta.(*conns.AWSClient).RedshiftServerlessClient(ctx), identifier, oldTags, newTags) } diff --git a/names/data/names_data.hcl b/names/data/names_data.hcl index b3eb999b0f27..cd3a0d323184 100644 --- a/names/data/names_data.hcl +++ b/names/data/names_data.hcl @@ -7460,7 +7460,7 @@ service "redshiftserverless" { sdk { id = "Redshift Serverless" - client_version = [1, 2] + client_version = [2] } names { From bf7b2841e8fb93aeacb88a56a44758b516110cba Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:33:23 +0200 Subject: [PATCH 02/14] feat: migrate r/endpoint_access to sdkv2 --- .../redshiftserverless/endpoint_access.go | 121 +++++++++++++++--- .../endpoint_access_test.go | 4 +- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/internal/service/redshiftserverless/endpoint_access.go b/internal/service/redshiftserverless/endpoint_access.go index c505a6d7d31b..34293ece010b 100644 --- a/internal/service/redshiftserverless/endpoint_access.go +++ b/internal/service/redshiftserverless/endpoint_access.go @@ -6,14 +6,17 @@ package redshiftserverless import ( "context" "log" + "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "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/redshiftserverless" + awstypes "github.com/aws/aws-sdk-go-v2/service/redshiftserverless/types" "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" "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/flex" tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" @@ -126,7 +129,7 @@ func resourceEndpointAccess() *schema.Resource { func resourceEndpointAccessCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) endpointName := d.Get("endpoint_name").(string) input := &redshiftserverless.CreateEndpointAccessInput{ @@ -139,20 +142,20 @@ func resourceEndpointAccessCreate(ctx context.Context, d *schema.ResourceData, m } if v, ok := d.GetOk(names.AttrSubnetIDs); ok && v.(*schema.Set).Len() > 0 { - input.SubnetIds = flex.ExpandStringSet(v.(*schema.Set)) + input.SubnetIds = flex.ExpandStringValueSet(v.(*schema.Set)) } if v, ok := d.GetOk(names.AttrVPCSecurityGroupIDs); ok && v.(*schema.Set).Len() > 0 { - input.VpcSecurityGroupIds = flex.ExpandStringSet(v.(*schema.Set)) + input.VpcSecurityGroupIds = flex.ExpandStringValueSet(v.(*schema.Set)) } - output, err := conn.CreateEndpointAccessWithContext(ctx, input) + output, err := conn.CreateEndpointAccess(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Redshift Serverless Endpoint Access (%s): %s", endpointName, err) } - d.SetId(aws.StringValue(output.Endpoint.EndpointName)) + d.SetId(aws.ToString(output.Endpoint.EndpointName)) if _, err := waitEndpointAccessActive(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for Redshift Serverless Endpoint Access (%s) create: %s", d.Id(), err) @@ -163,7 +166,7 @@ func resourceEndpointAccessCreate(ctx context.Context, d *schema.ResourceData, m func resourceEndpointAccessRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) endpointAccess, err := findEndpointAccessByName(ctx, conn, d.Id()) @@ -182,12 +185,12 @@ func resourceEndpointAccessRead(ctx context.Context, d *schema.ResourceData, met d.Set("endpoint_name", endpointAccess.EndpointName) d.Set("owner_account", d.Get("owner_account")) d.Set(names.AttrPort, endpointAccess.Port) - d.Set(names.AttrSubnetIDs, aws.StringValueSlice(endpointAccess.SubnetIds)) + d.Set(names.AttrSubnetIDs, endpointAccess.SubnetIds) if err := d.Set("vpc_endpoint", []interface{}{flattenVPCEndpoint(endpointAccess.VpcEndpoint)}); err != nil { return sdkdiag.AppendErrorf(diags, "setting vpc_endpoint: %s", err) } - d.Set(names.AttrVPCSecurityGroupIDs, tfslices.ApplyToAll(endpointAccess.VpcSecurityGroups, func(v *redshiftserverless.VpcSecurityGroupMembership) string { - return aws.StringValue(v.VpcSecurityGroupId) + d.Set(names.AttrVPCSecurityGroupIDs, tfslices.ApplyToAll(endpointAccess.VpcSecurityGroups, func(v awstypes.VpcSecurityGroupMembership) string { + return aws.ToString(v.VpcSecurityGroupId) })) d.Set("workgroup_name", endpointAccess.WorkgroupName) @@ -196,17 +199,17 @@ func resourceEndpointAccessRead(ctx context.Context, d *schema.ResourceData, met func resourceEndpointAccessUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) input := &redshiftserverless.UpdateEndpointAccessInput{ EndpointName: aws.String(d.Id()), } if v, ok := d.GetOk(names.AttrVPCSecurityGroupIDs); ok && v.(*schema.Set).Len() > 0 { - input.VpcSecurityGroupIds = flex.ExpandStringSet(v.(*schema.Set)) + input.VpcSecurityGroupIds = flex.ExpandStringValueSet(v.(*schema.Set)) } - _, err := conn.UpdateEndpointAccessWithContext(ctx, input) + _, err := conn.UpdateEndpointAccess(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Redshift Serverless Endpoint Access (%s): %s", d.Id(), err) @@ -221,14 +224,14 @@ func resourceEndpointAccessUpdate(ctx context.Context, d *schema.ResourceData, m func resourceEndpointAccessDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Endpoint Access: %s", d.Id()) - _, err := conn.DeleteEndpointAccessWithContext(ctx, &redshiftserverless.DeleteEndpointAccessInput{ + _, err := conn.DeleteEndpointAccess(ctx, &redshiftserverless.DeleteEndpointAccessInput{ EndpointName: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, redshiftserverless.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -242,3 +245,85 @@ func resourceEndpointAccessDelete(ctx context.Context, d *schema.ResourceData, m return diags } + +func findEndpointAccessByName(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.EndpointAccess, error) { + input := &redshiftserverless.GetEndpointAccessInput{ + EndpointName: aws.String(name), + } + + output, err := conn.GetEndpointAccess(ctx, input) + + if errs.IsA[*awstypes.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.Endpoint, nil +} + +func statusEndpointAccess(ctx context.Context, conn *redshiftserverless.Client, name string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := findEndpointAccessByName(ctx, conn, name) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, aws.ToString(output.EndpointStatus), nil + } +} + +func waitEndpointAccessActive(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.EndpointAccess, error) { //nolint:unparam + stateConf := &retry.StateChangeConf{ + Pending: []string{ + "CREATING", + "MODIFYING", + }, + Target: []string{ + "ACTIVE", + }, + Refresh: statusEndpointAccess(ctx, conn, name), + Timeout: 10 * time.Minute, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.EndpointAccess); ok { + return output, err + } + + return nil, err +} + +func waitEndpointAccessDeleted(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.EndpointAccess, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{ + "DELETING", + }, + Target: []string{}, + Refresh: statusEndpointAccess(ctx, conn, name), + Timeout: 10 * time.Minute, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.EndpointAccess); ok { + return output, err + } + + return nil, err +} diff --git a/internal/service/redshiftserverless/endpoint_access_test.go b/internal/service/redshiftserverless/endpoint_access_test.go index 4b9b8155ed8c..fee1e21ef8d0 100644 --- a/internal/service/redshiftserverless/endpoint_access_test.go +++ b/internal/service/redshiftserverless/endpoint_access_test.go @@ -112,7 +112,7 @@ func TestAccRedshiftServerlessEndpointAccess_disappears(t *testing.T) { func testAccCheckEndpointAccessDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_redshiftserverless_endpoint_access" { @@ -142,7 +142,7 @@ func testAccCheckEndpointAccessExists(ctx context.Context, n string) resource.Te return fmt.Errorf("Not found: %s", n) } - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) _, err := tfredshiftserverless.FindEndpointAccessByName(ctx, conn, rs.Primary.ID) From f307c317161de3ed31cac2e4837b3e96ed962b72 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:33:37 +0200 Subject: [PATCH 03/14] feat: migrate r/namespace to sdkv2 --- .../service/redshiftserverless/namespace.go | 129 ++++++++++++++---- .../redshiftserverless/namespace_test.go | 4 +- 2 files changed, 104 insertions(+), 29 deletions(-) diff --git a/internal/service/redshiftserverless/namespace.go b/internal/service/redshiftserverless/namespace.go index 1914c982abc4..46faee745ec9 100644 --- a/internal/service/redshiftserverless/namespace.go +++ b/internal/service/redshiftserverless/namespace.go @@ -10,14 +10,16 @@ import ( "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/arn" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "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/aws/arn" + "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" + awstypes "github.com/aws/aws-sdk-go-v2/service/redshiftserverless/types" "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" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "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" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -96,8 +98,8 @@ func resourceNamespace() *schema.Resource { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice(redshiftserverless.LogExport_Values(), false), + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.LogExport](), }, }, "manage_admin_password": { @@ -124,7 +126,7 @@ func resourceNamespace() *schema.Resource { func resourceNamespaceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) name := d.Get("namespace_name").(string) input := &redshiftserverless.CreateNamespaceInput{ @@ -153,7 +155,7 @@ func resourceNamespaceCreate(ctx context.Context, d *schema.ResourceData, meta i } if v, ok := d.GetOk("iam_roles"); ok && v.(*schema.Set).Len() > 0 { - input.IamRoles = flex.ExpandStringSet(v.(*schema.Set)) + input.IamRoles = flex.ExpandStringValueSet(v.(*schema.Set)) } if v, ok := d.GetOk(names.AttrKMSKeyID); ok { @@ -161,27 +163,27 @@ func resourceNamespaceCreate(ctx context.Context, d *schema.ResourceData, meta i } if v, ok := d.GetOk("log_exports"); ok && v.(*schema.Set).Len() > 0 { - input.LogExports = flex.ExpandStringSet(v.(*schema.Set)) + input.LogExports = flex.ExpandStringyValueSet[awstypes.LogExport](v.(*schema.Set)) } if v, ok := d.GetOk("manage_admin_password"); ok { input.ManageAdminPassword = aws.Bool(v.(bool)) } - output, err := conn.CreateNamespaceWithContext(ctx, input) + output, err := conn.CreateNamespace(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Redshift Serverless Namespace (%s): %s", name, err) } - d.SetId(aws.StringValue(output.Namespace.NamespaceName)) + d.SetId(aws.ToString(output.Namespace.NamespaceName)) return append(diags, resourceNamespaceRead(ctx, d, meta)...) } func resourceNamespaceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) output, err := findNamespaceByName(ctx, conn, d.Id()) @@ -195,16 +197,15 @@ func resourceNamespaceRead(ctx context.Context, d *schema.ResourceData, meta int return sdkdiag.AppendErrorf(diags, "reading Redshift Serverless Namespace (%s): %s", d.Id(), err) } - arn := aws.StringValue(output.NamespaceArn) d.Set("admin_password_secret_arn", output.AdminPasswordSecretArn) d.Set("admin_password_secret_kms_key_id", output.AdminPasswordSecretKmsKeyId) d.Set("admin_username", output.AdminUsername) - d.Set(names.AttrARN, arn) + d.Set(names.AttrARN, output.NamespaceArn) d.Set("db_name", output.DbName) d.Set("default_iam_role_arn", output.DefaultIamRoleArn) d.Set("iam_roles", flattenNamespaceIAMRoles(output.IamRoles)) d.Set(names.AttrKMSKeyID, output.KmsKeyId) - d.Set("log_exports", aws.StringValueSlice(output.LogExports)) + d.Set("log_exports", flex.FlattenStringyValueSet[awstypes.LogExport](output.LogExports)) d.Set("namespace_id", output.NamespaceId) d.Set("namespace_name", output.NamespaceName) @@ -213,7 +214,7 @@ func resourceNamespaceRead(ctx context.Context, d *schema.ResourceData, meta int func resourceNamespaceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) if d.HasChangesExcept(names.AttrTags, names.AttrTagsAll) { input := &redshiftserverless.UpdateNamespaceInput{ @@ -234,7 +235,7 @@ func resourceNamespaceUpdate(ctx context.Context, d *schema.ResourceData, meta i } if d.HasChange("iam_roles") { - input.IamRoles = flex.ExpandStringSet(d.Get("iam_roles").(*schema.Set)) + input.IamRoles = flex.ExpandStringValueSet(d.Get("iam_roles").(*schema.Set)) } if d.HasChange(names.AttrKMSKeyID) { @@ -242,14 +243,14 @@ func resourceNamespaceUpdate(ctx context.Context, d *schema.ResourceData, meta i } if d.HasChange("log_exports") { - input.LogExports = flex.ExpandStringSet(d.Get("log_exports").(*schema.Set)) + input.LogExports = flex.ExpandStringyValueSet[awstypes.LogExport](d.Get("log_exports").(*schema.Set)) } if d.HasChange("manage_admin_password") { input.ManageAdminPassword = aws.Bool(d.Get("manage_admin_password").(bool)) } - _, err := conn.UpdateNamespaceWithContext(ctx, input) + _, err := conn.UpdateNamespace(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Redshift Serverless Namespace (%s): %s", d.Id(), err) @@ -265,19 +266,19 @@ func resourceNamespaceUpdate(ctx context.Context, d *schema.ResourceData, meta i func resourceNamespaceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Namespace: %s", d.Id()) - _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, 10*time.Minute, + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.ConflictException](ctx, 10*time.Minute, func() (interface{}, error) { - return conn.DeleteNamespaceWithContext(ctx, &redshiftserverless.DeleteNamespaceInput{ + return conn.DeleteNamespace(ctx, &redshiftserverless.DeleteNamespaceInput{ NamespaceName: aws.String(d.Id()), }) }, // "ConflictException: There is an operation running on the namespace. Try deleting the namespace again later." - redshiftserverless.ErrCodeConflictException, "operation running") + "operation running") - if tfawserr.ErrCodeEquals(err, redshiftserverless.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -292,15 +293,89 @@ func resourceNamespaceDelete(ctx context.Context, d *schema.ResourceData, meta i return diags } +func findNamespaceByName(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Namespace, error) { + input := &redshiftserverless.GetNamespaceInput{ + NamespaceName: aws.String(name), + } + + output, err := conn.GetNamespace(ctx, input) + + if errs.IsA[*awstypes.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.Namespace, nil +} + +func statusNamespace(ctx context.Context, conn *redshiftserverless.Client, name string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := findNamespaceByName(ctx, conn, name) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, string(output.Status), nil + } +} + +func waitNamespaceDeleted(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Namespace, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.NamespaceStatusDeleting), + Target: []string{}, + Refresh: statusNamespace(ctx, conn, name), + Timeout: 10 * time.Minute, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Namespace); ok { + return output, err + } + + return nil, err +} + +func waitNamespaceUpdated(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Namespace, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.NamespaceStatusModifying), + Target: enum.Slice(awstypes.NamespaceStatusAvailable), + Refresh: statusNamespace(ctx, conn, name), + Timeout: 10 * time.Minute, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Namespace); ok { + return output, err + } + + return nil, err +} + var ( reIAMRole = regexache.MustCompile(`^\s*IamRole\((.*)\)\s*$`) ) -func flattenNamespaceIAMRoles(iamRoles []*string) []string { +func flattenNamespaceIAMRoles(iamRoles []string) []string { var tfList []string for _, iamRole := range iamRoles { - iamRole := aws.StringValue(iamRole) if arn.IsARN(iamRole) { tfList = append(tfList, iamRole) diff --git a/internal/service/redshiftserverless/namespace_test.go b/internal/service/redshiftserverless/namespace_test.go index fc2a31d86627..164d7f5f1e8e 100644 --- a/internal/service/redshiftserverless/namespace_test.go +++ b/internal/service/redshiftserverless/namespace_test.go @@ -244,7 +244,7 @@ func TestAccRedshiftServerlessNamespace_manageAdminPassword(t *testing.T) { func testAccCheckNamespaceDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_redshiftserverless_namespace" { @@ -279,7 +279,7 @@ func testAccCheckNamespaceExists(ctx context.Context, name string) resource.Test return fmt.Errorf("Redshift Serverless Namespace is not set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) _, err := tfredshiftserverless.FindNamespaceByName(ctx, conn, rs.Primary.ID) From f426059bf69910b2094cd7011166476e627e3a28 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:33:49 +0200 Subject: [PATCH 04/14] feat: migrate d/namespace to sdkv2 --- internal/service/redshiftserverless/namespace_data_source.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/redshiftserverless/namespace_data_source.go b/internal/service/redshiftserverless/namespace_data_source.go index 8b2250240d46..9994effb0caf 100644 --- a/internal/service/redshiftserverless/namespace_data_source.go +++ b/internal/service/redshiftserverless/namespace_data_source.go @@ -67,7 +67,7 @@ func dataSourceNamespace() *schema.Resource { func dataSourceNamespaceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) namespaceName := d.Get("namespace_name").(string) resource, err := findNamespaceByName(ctx, conn, namespaceName) From 56eb7943483678f0c4d543ea82482eb5d49a0d1d Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:34:00 +0200 Subject: [PATCH 05/14] feat: migrate d/credentials to sdkv2 --- .../redshiftserverless/credentials_data_source.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/service/redshiftserverless/credentials_data_source.go b/internal/service/redshiftserverless/credentials_data_source.go index 8951bdc7f7f0..9cb99fe750cf 100644 --- a/internal/service/redshiftserverless/credentials_data_source.go +++ b/internal/service/redshiftserverless/credentials_data_source.go @@ -7,8 +7,8 @@ import ( "context" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" "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" @@ -55,19 +55,19 @@ func dataSourceCredentials() *schema.Resource { func dataSourceCredentialsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) workgroupName := d.Get("workgroup_name").(string) input := &redshiftserverless.GetCredentialsInput{ WorkgroupName: aws.String(workgroupName), - DurationSeconds: aws.Int64(int64(d.Get("duration_seconds").(int))), + DurationSeconds: aws.Int32(int32(d.Get("duration_seconds").(int))), } if v, ok := d.GetOk("db_name"); ok { input.DbName = aws.String(v.(string)) } - creds, err := conn.GetCredentialsWithContext(ctx, input) + creds, err := conn.GetCredentials(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Redshift Serverless Credentials for Workgroup (%s): %s", workgroupName, err) @@ -77,7 +77,7 @@ func dataSourceCredentialsRead(ctx context.Context, d *schema.ResourceData, meta d.Set("db_password", creds.DbPassword) d.Set("db_user", creds.DbUser) - d.Set("expiration", aws.TimeValue(creds.Expiration).Format(time.RFC3339)) + d.Set("expiration", aws.ToTime(creds.Expiration).Format(time.RFC3339)) return diags } From 3d879aca73d9ced71c6f699f2569f7bb3b747843 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:34:17 +0200 Subject: [PATCH 06/14] feat: migrate r/resource_policy to sdkv2 --- .../redshiftserverless/resource_policy.go | 53 ++++++++++++++----- .../resource_policy_test.go | 4 +- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/internal/service/redshiftserverless/resource_policy.go b/internal/service/redshiftserverless/resource_policy.go index 1f296d8c1295..df5e871d0297 100644 --- a/internal/service/redshiftserverless/resource_policy.go +++ b/internal/service/redshiftserverless/resource_policy.go @@ -8,14 +8,16 @@ import ( "encoding/json" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "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/redshiftserverless" + awstypes "github.com/aws/aws-sdk-go-v2/service/redshiftserverless/types" "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" "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" tfiam "github.com/hashicorp/terraform-provider-aws/internal/service/iam" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -58,7 +60,7 @@ func resourceResourcePolicy() *schema.Resource { func resourceResourcePolicyPut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) arn := d.Get(names.AttrResourceARN).(string) @@ -67,25 +69,25 @@ func resourceResourcePolicyPut(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "policy (%s) is invalid JSON: %s", policy, err) } - input := redshiftserverless.PutResourcePolicyInput{ + input := &redshiftserverless.PutResourcePolicyInput{ ResourceArn: aws.String(arn), Policy: aws.String(policy), } - out, err := conn.PutResourcePolicyWithContext(ctx, &input) + out, err := conn.PutResourcePolicy(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "setting Redshift Serverless Resource Policy (%s): %s", arn, err) } - d.SetId(aws.StringValue(out.ResourcePolicy.ResourceArn)) + d.SetId(aws.ToString(out.ResourcePolicy.ResourceArn)) return append(diags, resourceResourcePolicyRead(ctx, d, meta)...) } func resourceResourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) out, err := findResourcePolicyByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { @@ -101,9 +103,9 @@ func resourceResourcePolicyRead(ctx context.Context, d *schema.ResourceData, met d.Set(names.AttrResourceARN, out.ResourceArn) doc := resourcePolicyDoc{} - log.Printf("policy is %s:", aws.StringValue(out.Policy)) + log.Printf("policy is %s:", aws.ToString(out.Policy)) - if err := json.Unmarshal([]byte(aws.StringValue(out.Policy)), &doc); err != nil { + if err := json.Unmarshal([]byte(aws.ToString(out.Policy)), &doc); err != nil { return sdkdiag.AppendErrorf(diags, "unmarshaling policy: %s", err) } @@ -139,14 +141,14 @@ func resourceResourcePolicyRead(ctx context.Context, d *schema.ResourceData, met func resourceResourcePolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Resource Policy: %s", d.Id()) - _, err := conn.DeleteResourcePolicyWithContext(ctx, &redshiftserverless.DeleteResourcePolicyInput{ + _, err := conn.DeleteResourcePolicy(ctx, &redshiftserverless.DeleteResourcePolicyInput{ ResourceArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, redshiftserverless.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -157,6 +159,31 @@ func resourceResourcePolicyDelete(ctx context.Context, d *schema.ResourceData, m return diags } +func findResourcePolicyByARN(ctx context.Context, conn *redshiftserverless.Client, arn string) (*awstypes.ResourcePolicy, error) { + input := &redshiftserverless.GetResourcePolicyInput{ + ResourceArn: aws.String(arn), + } + + output, err := conn.GetResourcePolicy(ctx, input) + + if errs.IsAErrorMessageContains[*awstypes.ResourceNotFoundException](err, "does not exist") { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.ResourcePolicy, nil +} + type resourcePolicyDoc struct { Version string `json:",omitempty"` Id string `json:",omitempty"` diff --git a/internal/service/redshiftserverless/resource_policy_test.go b/internal/service/redshiftserverless/resource_policy_test.go index 3d6c36db247d..1df1ab8be804 100644 --- a/internal/service/redshiftserverless/resource_policy_test.go +++ b/internal/service/redshiftserverless/resource_policy_test.go @@ -76,7 +76,7 @@ func TestAccRedshiftServerlessResourcePolicy_disappears(t *testing.T) { func testAccCheckResourcePolicyDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_redshiftserverless_resource_policy" { @@ -110,7 +110,7 @@ func testAccCheckResourcePolicyExists(ctx context.Context, name string) resource return fmt.Errorf("Redshift Serverless Resource Policy is not set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) _, err := tfredshiftserverless.FindResourcePolicyByARN(ctx, conn, rs.Primary.ID) From 4a69d2cddc901db30269d0ab3894006ad9ec20c8 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:34:26 +0200 Subject: [PATCH 07/14] feat: migrate r/snapshot to sdkv2 --- .../service/redshiftserverless/snapshot.go | 111 +++++++++++++++--- .../redshiftserverless/snapshot_test.go | 4 +- 2 files changed, 97 insertions(+), 18 deletions(-) diff --git a/internal/service/redshiftserverless/snapshot.go b/internal/service/redshiftserverless/snapshot.go index ea35f9c9b0c3..018a33b80c84 100644 --- a/internal/service/redshiftserverless/snapshot.go +++ b/internal/service/redshiftserverless/snapshot.go @@ -6,13 +6,17 @@ package redshiftserverless import ( "context" "log" + "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "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/redshiftserverless" + awstypes "github.com/aws/aws-sdk-go-v2/service/redshiftserverless/types" "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" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "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" @@ -87,7 +91,7 @@ func resourceSnapshot() *schema.Resource { func resourceSnapshotCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) input := redshiftserverless.CreateSnapshotInput{ NamespaceName: aws.String(d.Get("namespace_name").(string)), @@ -95,16 +99,16 @@ func resourceSnapshotCreate(ctx context.Context, d *schema.ResourceData, meta in } if v, ok := d.GetOk(names.AttrRetentionPeriod); ok { - input.RetentionPeriod = aws.Int64(int64(v.(int))) + input.RetentionPeriod = aws.Int32(int32(v.(int))) } - out, err := conn.CreateSnapshotWithContext(ctx, &input) + out, err := conn.CreateSnapshot(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Redshift Serverless Snapshot : %s", err) } - d.SetId(aws.StringValue(out.Snapshot.SnapshotName)) + d.SetId(aws.ToString(out.Snapshot.SnapshotName)) if _, err := waitSnapshotAvailable(ctx, conn, d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for Redshift Serverless Snapshot (%s) to be Available: %s", d.Id(), err) @@ -115,7 +119,7 @@ func resourceSnapshotCreate(ctx context.Context, d *schema.ResourceData, meta in func resourceSnapshotRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) out, err := findSnapshotByName(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { @@ -136,22 +140,22 @@ func resourceSnapshotRead(ctx context.Context, d *schema.ResourceData, meta inte d.Set("admin_username", out.AdminUsername) d.Set(names.AttrKMSKeyID, out.KmsKeyId) d.Set("owner_account", out.OwnerAccount) - d.Set("accounts_with_provisioned_restore_access", flex.FlattenStringSet(out.AccountsWithRestoreAccess)) - d.Set("accounts_with_restore_access", flex.FlattenStringSet(out.AccountsWithRestoreAccess)) + d.Set("accounts_with_provisioned_restore_access", flex.FlattenStringValueSet(out.AccountsWithRestoreAccess)) + d.Set("accounts_with_restore_access", flex.FlattenStringValueSet(out.AccountsWithRestoreAccess)) return diags } func resourceSnapshotUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) input := &redshiftserverless.UpdateSnapshotInput{ SnapshotName: aws.String(d.Id()), - RetentionPeriod: aws.Int64(int64(d.Get(names.AttrRetentionPeriod).(int))), + RetentionPeriod: aws.Int32(int32(d.Get(names.AttrRetentionPeriod).(int))), } - _, err := conn.UpdateSnapshotWithContext(ctx, input) + _, err := conn.UpdateSnapshot(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Redshift Serverless Snapshot (%s): %s", d.Id(), err) } @@ -161,14 +165,14 @@ func resourceSnapshotUpdate(ctx context.Context, d *schema.ResourceData, meta in func resourceSnapshotDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Snapshot: %s", d.Id()) - _, err := conn.DeleteSnapshotWithContext(ctx, &redshiftserverless.DeleteSnapshotInput{ + _, err := conn.DeleteSnapshot(ctx, &redshiftserverless.DeleteSnapshotInput{ SnapshotName: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, redshiftserverless.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -182,3 +186,78 @@ func resourceSnapshotDelete(ctx context.Context, d *schema.ResourceData, meta in return diags } + +func findSnapshotByName(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Snapshot, error) { + input := &redshiftserverless.GetSnapshotInput{ + SnapshotName: aws.String(name), + } + + output, err := conn.GetSnapshot(ctx, input) + + if errs.IsAErrorMessageContains[*awstypes.ResourceNotFoundException](err, "snapshot") { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.Snapshot, nil +} + +func statusSnapshot(ctx context.Context, conn *redshiftserverless.Client, name string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := findSnapshotByName(ctx, conn, name) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, string(output.Status), nil + } +} + +func waitSnapshotAvailable(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Snapshot, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.SnapshotStatusCreating), + Target: enum.Slice(awstypes.SnapshotStatusAvailable), + Refresh: statusSnapshot(ctx, conn, name), + Timeout: 10 * time.Minute, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Snapshot); ok { + return output, err + } + + return nil, err +} + +func waitSnapshotDeleted(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Snapshot, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.SnapshotStatusAvailable), + Target: []string{}, + Refresh: statusSnapshot(ctx, conn, name), + Timeout: 10 * time.Minute, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*awstypes.Snapshot); ok { + return output, err + } + + return nil, err +} diff --git a/internal/service/redshiftserverless/snapshot_test.go b/internal/service/redshiftserverless/snapshot_test.go index d7e1c3816577..eef518956ca5 100644 --- a/internal/service/redshiftserverless/snapshot_test.go +++ b/internal/service/redshiftserverless/snapshot_test.go @@ -86,7 +86,7 @@ func TestAccRedshiftServerlessSnapshot_disappears(t *testing.T) { func testAccCheckSnapshotDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_redshiftserverless_snapshot" { @@ -120,7 +120,7 @@ func testAccCheckSnapshotExists(ctx context.Context, name string) resource.TestC return fmt.Errorf("Redshift Serverless Snapshot is not set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) _, err := tfredshiftserverless.FindSnapshotByName(ctx, conn, rs.Primary.ID) From b38c33364877fad562f76d1219934c87bf9c4b1d Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:34:38 +0200 Subject: [PATCH 08/14] feat: migrate r/usage_limit to sdkv2 --- .../service/redshiftserverless/usage_limit.go | 85 ++++++++++++------- .../redshiftserverless/usage_limit_test.go | 4 +- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/internal/service/redshiftserverless/usage_limit.go b/internal/service/redshiftserverless/usage_limit.go index e2a710084206..cf1b3521de71 100644 --- a/internal/service/redshiftserverless/usage_limit.go +++ b/internal/service/redshiftserverless/usage_limit.go @@ -7,13 +7,15 @@ import ( "context" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "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/redshiftserverless" + awstypes "github.com/aws/aws-sdk-go-v2/service/redshiftserverless/types" "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" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "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" @@ -42,17 +44,17 @@ func resourceUsageLimit() *schema.Resource { Required: true, }, "breach_action": { - Type: schema.TypeString, - Optional: true, - Default: redshiftserverless.UsageLimitBreachActionLog, - ValidateFunc: validation.StringInSlice(redshiftserverless.UsageLimitBreachAction_Values(), false), + Type: schema.TypeString, + Optional: true, + Default: awstypes.UsageLimitBreachActionLog, + ValidateDiagFunc: enum.Validate[awstypes.UsageLimitBreachAction](), }, "period": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: redshiftserverless.UsageLimitPeriodMonthly, - ValidateFunc: validation.StringInSlice(redshiftserverless.UsageLimitPeriod_Values(), false), + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: awstypes.UsageLimitPeriodMonthly, + ValidateDiagFunc: enum.Validate[awstypes.UsageLimitPeriod](), }, names.AttrResourceARN: { Type: schema.TypeString, @@ -61,9 +63,9 @@ func resourceUsageLimit() *schema.Resource { ValidateFunc: verify.ValidARN, }, "usage_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(redshiftserverless.UsageLimitUsageType_Values(), false), + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.UsageLimitUsageType](), }, }, } @@ -71,36 +73,36 @@ func resourceUsageLimit() *schema.Resource { func resourceUsageLimitCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) input := redshiftserverless.CreateUsageLimitInput{ Amount: aws.Int64(int64(d.Get("amount").(int))), ResourceArn: aws.String(d.Get(names.AttrResourceARN).(string)), - UsageType: aws.String(d.Get("usage_type").(string)), + UsageType: awstypes.UsageLimitUsageType(d.Get("usage_type").(string)), } if v, ok := d.GetOk("period"); ok { - input.Period = aws.String(v.(string)) + input.Period = awstypes.UsageLimitPeriod(v.(string)) } if v, ok := d.GetOk("breach_action"); ok { - input.BreachAction = aws.String(v.(string)) + input.BreachAction = awstypes.UsageLimitBreachAction(v.(string)) } - out, err := conn.CreateUsageLimitWithContext(ctx, &input) + out, err := conn.CreateUsageLimit(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Redshift Serverless Usage Limit : %s", err) } - d.SetId(aws.StringValue(out.UsageLimit.UsageLimitId)) + d.SetId(aws.ToString(out.UsageLimit.UsageLimitId)) return append(diags, resourceUsageLimitRead(ctx, d, meta)...) } func resourceUsageLimitRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) out, err := findUsageLimitByName(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { @@ -125,7 +127,7 @@ func resourceUsageLimitRead(ctx context.Context, d *schema.ResourceData, meta in func resourceUsageLimitUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) input := &redshiftserverless.UpdateUsageLimitInput{ UsageLimitId: aws.String(d.Id()), @@ -136,10 +138,10 @@ func resourceUsageLimitUpdate(ctx context.Context, d *schema.ResourceData, meta } if d.HasChange("breach_action") { - input.BreachAction = aws.String(d.Get("breach_action").(string)) + input.BreachAction = awstypes.UsageLimitBreachAction(d.Get("breach_action").(string)) } - _, err := conn.UpdateUsageLimitWithContext(ctx, input) + _, err := conn.UpdateUsageLimit(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Redshift Serverless Usage Limit (%s): %s", d.Id(), err) } @@ -149,14 +151,14 @@ func resourceUsageLimitUpdate(ctx context.Context, d *schema.ResourceData, meta func resourceUsageLimitDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Usage Limit: %s", d.Id()) - _, err := conn.DeleteUsageLimitWithContext(ctx, &redshiftserverless.DeleteUsageLimitInput{ + _, err := conn.DeleteUsageLimit(ctx, &redshiftserverless.DeleteUsageLimitInput{ UsageLimitId: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, redshiftserverless.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -166,3 +168,28 @@ func resourceUsageLimitDelete(ctx context.Context, d *schema.ResourceData, meta return diags } + +func findUsageLimitByName(ctx context.Context, conn *redshiftserverless.Client, id string) (*awstypes.UsageLimit, error) { + input := &redshiftserverless.GetUsageLimitInput{ + UsageLimitId: aws.String(id), + } + + output, err := conn.GetUsageLimit(ctx, input) + + if errs.IsAErrorMessageContains[*awstypes.ValidationException](err, "does not exist") { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.UsageLimit, nil +} diff --git a/internal/service/redshiftserverless/usage_limit_test.go b/internal/service/redshiftserverless/usage_limit_test.go index 632a382e4ef0..1fb53552c1f7 100644 --- a/internal/service/redshiftserverless/usage_limit_test.go +++ b/internal/service/redshiftserverless/usage_limit_test.go @@ -82,7 +82,7 @@ func TestAccRedshiftServerlessUsageLimit_disappears(t *testing.T) { func testAccCheckUsageLimitDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_redshiftserverless_usage_limit" { @@ -116,7 +116,7 @@ func testAccCheckUsageLimitExists(ctx context.Context, name string) resource.Tes return fmt.Errorf("Redshift Serverless Usage Limit is not set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) _, err := tfredshiftserverless.FindUsageLimitByName(ctx, conn, rs.Primary.ID) From fe37a3d6a761326cfe9f918359ff01aa47ce6555 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:34:56 +0200 Subject: [PATCH 09/14] feat: migrate r/workgroup to sdkv2 --- .../redshiftserverless/exports_test.go | 1 + .../service/redshiftserverless/workgroup.go | 179 +++++++----------- .../redshiftserverless/workgroup_test.go | 4 +- 3 files changed, 76 insertions(+), 108 deletions(-) diff --git a/internal/service/redshiftserverless/exports_test.go b/internal/service/redshiftserverless/exports_test.go index 4e5a0d27de0b..02e505238da1 100644 --- a/internal/service/redshiftserverless/exports_test.go +++ b/internal/service/redshiftserverless/exports_test.go @@ -19,4 +19,5 @@ var ( FindResourcePolicyByARN = findResourcePolicyByARN FindSnapshotByName = findSnapshotByName FindUsageLimitByName = findUsageLimitByName + FindWorkgroupByName = findWorkgroupByName ) diff --git a/internal/service/redshiftserverless/workgroup.go b/internal/service/redshiftserverless/workgroup.go index 72608454afc8..5020407ce42a 100644 --- a/internal/service/redshiftserverless/workgroup.go +++ b/internal/service/redshiftserverless/workgroup.go @@ -9,14 +9,16 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "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/redshiftserverless" + awstypes "github.com/aws/aws-sdk-go-v2/service/redshiftserverless/types" "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" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "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" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -207,7 +209,7 @@ func resourceWorkgroup() *schema.Resource { func resourceWorkgroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) name := d.Get("workgroup_name").(string) input := redshiftserverless.CreateWorkgroupInput{ @@ -217,7 +219,7 @@ func resourceWorkgroupCreate(ctx context.Context, d *schema.ResourceData, meta i } if v, ok := d.GetOk("base_capacity"); ok { - input.BaseCapacity = aws.Int64(int64(v.(int))) + input.BaseCapacity = aws.Int32(int32(v.(int))) } if v, ok := d.GetOk("config_parameter"); ok && v.(*schema.Set).Len() > 0 { @@ -229,11 +231,11 @@ func resourceWorkgroupCreate(ctx context.Context, d *schema.ResourceData, meta i } if v, ok := d.GetOk(names.AttrMaxCapacity); ok { - input.MaxCapacity = aws.Int64(int64(v.(int))) + input.MaxCapacity = aws.Int32(int32(v.(int))) } if v, ok := d.GetOk(names.AttrPort); ok { - input.Port = aws.Int64(int64(v.(int))) + input.Port = aws.Int32(int32(v.(int))) } if v, ok := d.GetOk(names.AttrPubliclyAccessible); ok { @@ -241,20 +243,20 @@ func resourceWorkgroupCreate(ctx context.Context, d *schema.ResourceData, meta i } if v, ok := d.GetOk(names.AttrSecurityGroupIDs); ok && v.(*schema.Set).Len() > 0 { - input.SecurityGroupIds = flex.ExpandStringSet(v.(*schema.Set)) + input.SecurityGroupIds = flex.ExpandStringValueSet(v.(*schema.Set)) } if v, ok := d.GetOk(names.AttrSubnetIDs); ok && v.(*schema.Set).Len() > 0 { - input.SubnetIds = flex.ExpandStringSet(v.(*schema.Set)) + input.SubnetIds = flex.ExpandStringValueSet(v.(*schema.Set)) } - output, err := conn.CreateWorkgroupWithContext(ctx, &input) + output, err := conn.CreateWorkgroup(ctx, &input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Redshift Serverless Workgroup (%s): %s", name, err) } - d.SetId(aws.StringValue(output.Workgroup.WorkgroupName)) + d.SetId(aws.ToString(output.Workgroup.WorkgroupName)) if _, err := waitWorkgroupAvailable(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for Redshift Serverless Workgroup (%s) create: %s", d.Id(), err) @@ -265,9 +267,9 @@ func resourceWorkgroupCreate(ctx context.Context, d *schema.ResourceData, meta i func resourceWorkgroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) - out, err := FindWorkgroupByName(ctx, conn, d.Id()) + out, err := findWorkgroupByName(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Redshift Serverless Workgroup (%s) not found, removing from state", d.Id()) @@ -279,8 +281,7 @@ func resourceWorkgroupRead(ctx context.Context, d *schema.ResourceData, meta int return sdkdiag.AppendErrorf(diags, "reading Redshift Serverless Workgroup (%s): %s", d.Id(), err) } - arn := aws.StringValue(out.WorkgroupArn) - d.Set(names.AttrARN, arn) + d.Set(names.AttrARN, out.WorkgroupArn) d.Set("base_capacity", out.BaseCapacity) if err := d.Set("config_parameter", flattenConfigParameters(out.ConfigParameters)); err != nil { return sdkdiag.AppendErrorf(diags, "setting config_parameter: %s", err) @@ -293,8 +294,8 @@ func resourceWorkgroupRead(ctx context.Context, d *schema.ResourceData, meta int d.Set("namespace_name", out.NamespaceName) d.Set(names.AttrPort, flattenEndpoint(out.Endpoint)[names.AttrPort]) d.Set(names.AttrPubliclyAccessible, out.PubliclyAccessible) - d.Set(names.AttrSecurityGroupIDs, flex.FlattenStringSet(out.SecurityGroupIds)) - d.Set(names.AttrSubnetIDs, flex.FlattenStringSet(out.SubnetIds)) + d.Set(names.AttrSecurityGroupIDs, flex.FlattenStringValueSet(out.SecurityGroupIds)) + d.Set(names.AttrSubnetIDs, flex.FlattenStringValueSet(out.SubnetIds)) d.Set("workgroup_id", out.WorkgroupId) d.Set("workgroup_name", out.WorkgroupName) @@ -303,7 +304,7 @@ func resourceWorkgroupRead(ctx context.Context, d *schema.ResourceData, meta int func resourceWorkgroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) checkCapacityChange := func(key string) (bool, int, int) { o, n := d.GetChange(key) @@ -329,47 +330,47 @@ func resourceWorkgroupUpdate(ctx context.Context, d *schema.ResourceData, meta i case hasMaxCapacityChange && newMaxCapacity == 0: if err := updateWorkgroup(ctx, conn, - &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int64(-1), WorkgroupName: aws.String(d.Id())}, + &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int32(-1), WorkgroupName: aws.String(d.Id())}, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendFromErr(diags, err) } case hasBaseCapacityChange && hasMaxCapacityChange && (oldMaxCapacity == 0 || newBaseCapacity <= oldMaxCapacity): if err := updateWorkgroup(ctx, conn, - &redshiftserverless.UpdateWorkgroupInput{BaseCapacity: aws.Int64(int64(newBaseCapacity)), WorkgroupName: aws.String(d.Id())}, + &redshiftserverless.UpdateWorkgroupInput{BaseCapacity: aws.Int32(int32(newBaseCapacity)), WorkgroupName: aws.String(d.Id())}, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendFromErr(diags, err) } if err := updateWorkgroup(ctx, conn, - &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int64(int64(newMaxCapacity)), WorkgroupName: aws.String(d.Id())}, + &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int32(int32(newMaxCapacity)), WorkgroupName: aws.String(d.Id())}, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendFromErr(diags, err) } case hasBaseCapacityChange && hasMaxCapacityChange && newBaseCapacity > oldMaxCapacity: if err := updateWorkgroup(ctx, conn, - &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int64(int64(newMaxCapacity)), WorkgroupName: aws.String(d.Id())}, + &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int32(int32(newMaxCapacity)), WorkgroupName: aws.String(d.Id())}, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendFromErr(diags, err) } if err := updateWorkgroup(ctx, conn, - &redshiftserverless.UpdateWorkgroupInput{BaseCapacity: aws.Int64(int64(newBaseCapacity)), WorkgroupName: aws.String(d.Id())}, + &redshiftserverless.UpdateWorkgroupInput{BaseCapacity: aws.Int32(int32(newBaseCapacity)), WorkgroupName: aws.String(d.Id())}, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendFromErr(diags, err) } case hasBaseCapacityChange: if err := updateWorkgroup(ctx, conn, - &redshiftserverless.UpdateWorkgroupInput{BaseCapacity: aws.Int64(int64(newBaseCapacity)), WorkgroupName: aws.String(d.Id())}, + &redshiftserverless.UpdateWorkgroupInput{BaseCapacity: aws.Int32(int32(newBaseCapacity)), WorkgroupName: aws.String(d.Id())}, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendFromErr(diags, err) } case hasMaxCapacityChange: if err := updateWorkgroup(ctx, conn, - &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int64(int64(newMaxCapacity)), WorkgroupName: aws.String(d.Id())}, + &redshiftserverless.UpdateWorkgroupInput{MaxCapacity: aws.Int32(int32(newMaxCapacity)), WorkgroupName: aws.String(d.Id())}, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -399,7 +400,7 @@ func resourceWorkgroupUpdate(ctx context.Context, d *schema.ResourceData, meta i if d.HasChange(names.AttrPort) { input := &redshiftserverless.UpdateWorkgroupInput{ - Port: aws.Int64(int64(d.Get(names.AttrPort).(int))), + Port: aws.Int32(int32(d.Get(names.AttrPort).(int))), WorkgroupName: aws.String(d.Id()), } @@ -421,7 +422,7 @@ func resourceWorkgroupUpdate(ctx context.Context, d *schema.ResourceData, meta i if d.HasChange(names.AttrSecurityGroupIDs) { input := &redshiftserverless.UpdateWorkgroupInput{ - SecurityGroupIds: flex.ExpandStringSet(d.Get(names.AttrSecurityGroupIDs).(*schema.Set)), + SecurityGroupIds: flex.ExpandStringValueSet(d.Get(names.AttrSecurityGroupIDs).(*schema.Set)), WorkgroupName: aws.String(d.Id()), } @@ -432,7 +433,7 @@ func resourceWorkgroupUpdate(ctx context.Context, d *schema.ResourceData, meta i if d.HasChange(names.AttrSubnetIDs) { input := &redshiftserverless.UpdateWorkgroupInput{ - SubnetIds: flex.ExpandStringSet(d.Get(names.AttrSubnetIDs).(*schema.Set)), + SubnetIds: flex.ExpandStringValueSet(d.Get(names.AttrSubnetIDs).(*schema.Set)), WorkgroupName: aws.String(d.Id()), } @@ -446,19 +447,19 @@ func resourceWorkgroupUpdate(ctx context.Context, d *schema.ResourceData, meta i func resourceWorkgroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Workgroup: %s", d.Id()) - _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, 10*time.Minute, + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.ConflictException](ctx, 10*time.Minute, func() (interface{}, error) { - return conn.DeleteWorkgroupWithContext(ctx, &redshiftserverless.DeleteWorkgroupInput{ + return conn.DeleteWorkgroup(ctx, &redshiftserverless.DeleteWorkgroupInput{ WorkgroupName: aws.String(d.Id()), }) }, // "ConflictException: There is an operation running on the workgroup. Try deleting the workgroup again later." - redshiftserverless.ErrCodeConflictException, "operation running") + "operation running") - if tfawserr.ErrCodeEquals(err, redshiftserverless.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -473,9 +474,9 @@ func resourceWorkgroupDelete(ctx context.Context, d *schema.ResourceData, meta i return diags } -func updateWorkgroup(ctx context.Context, conn *redshiftserverless.RedshiftServerless, input *redshiftserverless.UpdateWorkgroupInput, timeout time.Duration) error { - name := aws.StringValue(input.WorkgroupName) - _, err := conn.UpdateWorkgroupWithContext(ctx, input) +func updateWorkgroup(ctx context.Context, conn *redshiftserverless.Client, input *redshiftserverless.UpdateWorkgroupInput, timeout time.Duration) error { + name := aws.ToString(input.WorkgroupName) + _, err := conn.UpdateWorkgroup(ctx, input) if err != nil { return fmt.Errorf("updating Redshift Serverless Workgroup (%s): %w", name, err) @@ -488,14 +489,14 @@ func updateWorkgroup(ctx context.Context, conn *redshiftserverless.RedshiftServe return nil } -func FindWorkgroupByName(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.Workgroup, error) { +func findWorkgroupByName(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Workgroup, error) { input := &redshiftserverless.GetWorkgroupInput{ WorkgroupName: aws.String(name), } - output, err := conn.GetWorkgroupWithContext(ctx, input) + output, err := conn.GetWorkgroup(ctx, input) - if tfawserr.ErrCodeEquals(err, redshiftserverless.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -513,9 +514,9 @@ func FindWorkgroupByName(ctx context.Context, conn *redshiftserverless.RedshiftS return output.Workgroup, nil } -func statusWorkgroup(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) retry.StateRefreshFunc { +func statusWorkgroup(ctx context.Context, conn *redshiftserverless.Client, name string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - output, err := FindWorkgroupByName(ctx, conn, name) + output, err := findWorkgroupByName(ctx, conn, name) if tfresource.NotFound(err) { return nil, "", nil @@ -525,30 +526,30 @@ func statusWorkgroup(ctx context.Context, conn *redshiftserverless.RedshiftServe return nil, "", err } - return output, aws.StringValue(output.Status), nil + return output, string(output.Status), nil } } -func waitWorkgroupAvailable(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string, wait time.Duration) (*redshiftserverless.Workgroup, error) { //nolint:unparam +func waitWorkgroupAvailable(ctx context.Context, conn *redshiftserverless.Client, name string, wait time.Duration) (*awstypes.Workgroup, error) { //nolint:unparam stateConf := &retry.StateChangeConf{ - Pending: []string{redshiftserverless.WorkgroupStatusCreating, redshiftserverless.WorkgroupStatusModifying}, - Target: []string{redshiftserverless.WorkgroupStatusAvailable}, + Pending: enum.Slice(awstypes.WorkgroupStatusCreating, awstypes.WorkgroupStatusModifying), + Target: enum.Slice(awstypes.WorkgroupStatusAvailable), Refresh: statusWorkgroup(ctx, conn, name), Timeout: wait, } outputRaw, err := stateConf.WaitForStateContext(ctx) - if output, ok := outputRaw.(*redshiftserverless.Workgroup); ok { + if output, ok := outputRaw.(*awstypes.Workgroup); ok { return output, err } return nil, err } -func waitWorkgroupDeleted(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string, wait time.Duration) (*redshiftserverless.Workgroup, error) { +func waitWorkgroupDeleted(ctx context.Context, conn *redshiftserverless.Client, name string, wait time.Duration) (*awstypes.Workgroup, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{redshiftserverless.WorkgroupStatusAvailable, redshiftserverless.WorkgroupStatusModifying, redshiftserverless.WorkgroupStatusDeleting}, + Pending: enum.Slice(awstypes.WorkgroupStatusAvailable, awstypes.WorkgroupStatusModifying, awstypes.WorkgroupStatusDeleting), Target: []string{}, Refresh: statusWorkgroup(ctx, conn, name), Timeout: wait, @@ -556,19 +557,15 @@ func waitWorkgroupDeleted(ctx context.Context, conn *redshiftserverless.Redshift outputRaw, err := stateConf.WaitForStateContext(ctx) - if output, ok := outputRaw.(*redshiftserverless.Workgroup); ok { + if output, ok := outputRaw.(*awstypes.Workgroup); ok { return output, err } return nil, err } -func expandConfigParameter(tfMap map[string]interface{}) *redshiftserverless.ConfigParameter { - if tfMap == nil { - return nil - } - - apiObject := &redshiftserverless.ConfigParameter{} +func expandConfigParameter(tfMap map[string]interface{}) awstypes.ConfigParameter { + apiObject := awstypes.ConfigParameter{} if v, ok := tfMap["parameter_key"].(string); ok { apiObject.ParameterKey = aws.String(v) @@ -581,12 +578,12 @@ func expandConfigParameter(tfMap map[string]interface{}) *redshiftserverless.Con return apiObject } -func expandConfigParameters(tfList []interface{}) []*redshiftserverless.ConfigParameter { +func expandConfigParameters(tfList []interface{}) []awstypes.ConfigParameter { if len(tfList) == 0 { return nil } - var apiObjects []*redshiftserverless.ConfigParameter + var apiObjects []awstypes.ConfigParameter for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) @@ -595,36 +592,26 @@ func expandConfigParameters(tfList []interface{}) []*redshiftserverless.ConfigPa continue } - apiObject := expandConfigParameter(tfMap) - - if apiObject == nil { - continue - } - - apiObjects = append(apiObjects, apiObject) + apiObjects = append(apiObjects, expandConfigParameter(tfMap)) } return apiObjects } -func flattenConfigParameter(apiObject *redshiftserverless.ConfigParameter) map[string]interface{} { - if apiObject == nil { - return nil - } - +func flattenConfigParameter(apiObject awstypes.ConfigParameter) map[string]interface{} { tfMap := map[string]interface{}{} if v := apiObject.ParameterKey; v != nil { - tfMap["parameter_key"] = aws.StringValue(v) + tfMap["parameter_key"] = aws.ToString(v) } if v := apiObject.ParameterValue; v != nil { - tfMap["parameter_value"] = aws.StringValue(v) + tfMap["parameter_value"] = aws.ToString(v) } return tfMap } -func flattenConfigParameters(apiObjects []*redshiftserverless.ConfigParameter) []interface{} { +func flattenConfigParameters(apiObjects []awstypes.ConfigParameter) []interface{} { if len(apiObjects) == 0 { return nil } @@ -632,28 +619,24 @@ func flattenConfigParameters(apiObjects []*redshiftserverless.ConfigParameter) [ var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - tfList = append(tfList, flattenConfigParameter(apiObject)) } return tfList } -func flattenEndpoint(apiObject *redshiftserverless.Endpoint) map[string]interface{} { +func flattenEndpoint(apiObject *awstypes.Endpoint) map[string]interface{} { if apiObject == nil { return nil } tfMap := map[string]interface{}{} if v := apiObject.Address; v != nil { - tfMap[names.AttrAddress] = aws.StringValue(v) + tfMap[names.AttrAddress] = aws.ToString(v) } if v := apiObject.Port; v != nil { - tfMap[names.AttrPort] = aws.Int64Value(v) + tfMap[names.AttrPort] = aws.ToInt32(v) } if v := apiObject.VpcEndpoints; v != nil { @@ -663,7 +646,7 @@ func flattenEndpoint(apiObject *redshiftserverless.Endpoint) map[string]interfac return tfMap } -func flattenVPCEndpoints(apiObjects []*redshiftserverless.VpcEndpoint) []interface{} { +func flattenVPCEndpoints(apiObjects []awstypes.VpcEndpoint) []interface{} { if len(apiObjects) == 0 { return nil } @@ -671,29 +654,21 @@ func flattenVPCEndpoints(apiObjects []*redshiftserverless.VpcEndpoint) []interfa var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenVPCEndpoint(apiObject)) + tfList = append(tfList, flattenVPCEndpoint(&apiObject)) } return tfList } -func flattenVPCEndpoint(apiObject *redshiftserverless.VpcEndpoint) map[string]interface{} { - if apiObject == nil { - return nil - } - +func flattenVPCEndpoint(apiObject *awstypes.VpcEndpoint) map[string]interface{} { tfMap := map[string]interface{}{} if v := apiObject.VpcEndpointId; v != nil { - tfMap[names.AttrVPCEndpointID] = aws.StringValue(v) + tfMap[names.AttrVPCEndpointID] = aws.ToString(v) } if v := apiObject.VpcId; v != nil { - tfMap[names.AttrVPCID] = aws.StringValue(v) + tfMap[names.AttrVPCID] = aws.ToString(v) } if v := apiObject.NetworkInterfaces; v != nil { @@ -702,7 +677,7 @@ func flattenVPCEndpoint(apiObject *redshiftserverless.VpcEndpoint) map[string]in return tfMap } -func flattenNetworkInterfaces(apiObjects []*redshiftserverless.NetworkInterface) []interface{} { +func flattenNetworkInterfaces(apiObjects []awstypes.NetworkInterface) []interface{} { if len(apiObjects) == 0 { return nil } @@ -710,37 +685,29 @@ func flattenNetworkInterfaces(apiObjects []*redshiftserverless.NetworkInterface) var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - tfList = append(tfList, flattenNetworkInterface(apiObject)) } return tfList } -func flattenNetworkInterface(apiObject *redshiftserverless.NetworkInterface) map[string]interface{} { - if apiObject == nil { - return nil - } - +func flattenNetworkInterface(apiObject awstypes.NetworkInterface) map[string]interface{} { tfMap := map[string]interface{}{} if v := apiObject.AvailabilityZone; v != nil { - tfMap[names.AttrAvailabilityZone] = aws.StringValue(v) + tfMap[names.AttrAvailabilityZone] = aws.ToString(v) } if v := apiObject.NetworkInterfaceId; v != nil { - tfMap[names.AttrNetworkInterfaceID] = aws.StringValue(v) + tfMap[names.AttrNetworkInterfaceID] = aws.ToString(v) } if v := apiObject.PrivateIpAddress; v != nil { - tfMap["private_ip_address"] = aws.StringValue(v) + tfMap["private_ip_address"] = aws.ToString(v) } if v := apiObject.SubnetId; v != nil { - tfMap[names.AttrSubnetID] = aws.StringValue(v) + tfMap[names.AttrSubnetID] = aws.ToString(v) } return tfMap } diff --git a/internal/service/redshiftserverless/workgroup_test.go b/internal/service/redshiftserverless/workgroup_test.go index 21a895b6ac2f..446dbe57c0ac 100644 --- a/internal/service/redshiftserverless/workgroup_test.go +++ b/internal/service/redshiftserverless/workgroup_test.go @@ -321,7 +321,7 @@ func TestAccRedshiftServerlessWorkgroup_port(t *testing.T) { func testAccCheckWorkgroupDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_redshiftserverless_workgroup" { @@ -355,7 +355,7 @@ func testAccCheckWorkgroupExists(ctx context.Context, name string) resource.Test return fmt.Errorf("Redshift Serverless Workgroup ID is not set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).RedshiftServerlessClient(ctx) _, err := tfredshiftserverless.FindWorkgroupByName(ctx, conn, rs.Primary.ID) From 6d65444e71dc0ee1226a35977190bea444cd64e1 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:35:05 +0200 Subject: [PATCH 10/14] feat: migrate d/workgroup to sdkv2 --- internal/service/redshiftserverless/workgroup_data_source.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/redshiftserverless/workgroup_data_source.go b/internal/service/redshiftserverless/workgroup_data_source.go index f7108c29c2e3..3a3bc71fd812 100644 --- a/internal/service/redshiftserverless/workgroup_data_source.go +++ b/internal/service/redshiftserverless/workgroup_data_source.go @@ -119,11 +119,11 @@ func dataSourceWorkgroup() *schema.Resource { func dataSourceWorkgroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).RedshiftServerlessConn(ctx) + conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) workgroupName := d.Get("workgroup_name").(string) - resource, err := FindWorkgroupByName(ctx, conn, workgroupName) + resource, err := findWorkgroupByName(ctx, conn, workgroupName) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Redshift Serverless Workgroup (%s): %s", workgroupName, err) From 416434d256995398d8a55e4703d3e44babb04259 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:35:19 +0200 Subject: [PATCH 11/14] feat: migrate sweepers --- internal/service/redshiftserverless/sweep.go | 72 ++++++++------------ 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/internal/service/redshiftserverless/sweep.go b/internal/service/redshiftserverless/sweep.go index e4866cf35d75..ca954331affc 100644 --- a/internal/service/redshiftserverless/sweep.go +++ b/internal/service/redshiftserverless/sweep.go @@ -7,12 +7,12 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/redshiftserverless" "github.com/hashicorp/go-multierror" "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() { @@ -41,37 +41,33 @@ func sweepNamespaces(region string) error { if err != nil { return fmt.Errorf("error getting client: %w", err) } - conn := client.RedshiftServerlessConn(ctx) + conn := client.RedshiftServerlessClient(ctx) input := &redshiftserverless.ListNamespacesInput{} sweepResources := make([]sweep.Sweepable, 0) var errs *multierror.Error - err = conn.ListNamespacesPagesWithContext(ctx, input, func(page *redshiftserverless.ListNamespacesOutput, lastPage bool) bool { - if len(page.Namespaces) == 0 { - log.Print("[DEBUG] No Redshift Serverless Namespaces to sweep") - return !lastPage + pages := redshiftserverless.NewListNamespacesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + errs = multierror.Append(errs, fmt.Errorf("error describing Redshift Serverless Namespaces: %w", err)) } for _, namespace := range page.Namespaces { r := resourceNamespace() d := r.Data(nil) - d.SetId(aws.StringValue(namespace.NamespaceName)) + d.SetId(aws.ToString(namespace.NamespaceName)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if err != nil { - errs = multierror.Append(errs, fmt.Errorf("error describing Redshift Serverless Namespaces: %w", err)) } if err = sweep.SweepOrchestrator(ctx, sweepResources); err != nil { errs = multierror.Append(errs, fmt.Errorf("error sweeping Redshift Serverless Namespaces for %s: %w", region, err)) } - if awsv1.SkipSweepError(errs.ErrorOrNil()) { + if awsv2.SkipSweepError(errs.ErrorOrNil()) { log.Printf("[WARN] Skipping Redshift Serverless Namespaces sweep for %s: %s", region, errs) return nil } @@ -85,37 +81,33 @@ func sweepWorkgroups(region string) error { if err != nil { return fmt.Errorf("error getting client: %w", err) } - conn := client.RedshiftServerlessConn(ctx) + conn := client.RedshiftServerlessClient(ctx) input := &redshiftserverless.ListWorkgroupsInput{} sweepResources := make([]sweep.Sweepable, 0) var errs *multierror.Error - err = conn.ListWorkgroupsPagesWithContext(ctx, input, func(page *redshiftserverless.ListWorkgroupsOutput, lastPage bool) bool { - if len(page.Workgroups) == 0 { - log.Print("[DEBUG] No Redshift Serverless Workgroups to sweep") - return !lastPage + pages := redshiftserverless.NewListWorkgroupsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + errs = multierror.Append(errs, fmt.Errorf("error describing Redshift Serverless Workgroups: %w", err)) } for _, workgroup := range page.Workgroups { r := resourceWorkgroup() d := r.Data(nil) - d.SetId(aws.StringValue(workgroup.WorkgroupName)) + d.SetId(aws.ToString(workgroup.WorkgroupName)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if err != nil { - errs = multierror.Append(errs, fmt.Errorf("error describing Redshift Serverless Workgroups: %w", err)) } if err = sweep.SweepOrchestrator(ctx, sweepResources); err != nil { errs = multierror.Append(errs, fmt.Errorf("error sweeping Redshift Serverless Workgroups for %s: %w", region, err)) } - if awsv1.SkipSweepError(errs.ErrorOrNil()) { + if awsv2.SkipSweepError(errs.ErrorOrNil()) { log.Printf("[WARN] Skipping Redshift Serverless Workgroups sweep for %s: %s", region, errs) return nil } @@ -129,37 +121,33 @@ func sweepSnapshots(region string) error { if err != nil { return fmt.Errorf("error getting client: %w", err) } - conn := client.RedshiftServerlessConn(ctx) + conn := client.RedshiftServerlessClient(ctx) input := &redshiftserverless.ListSnapshotsInput{} sweepResources := make([]sweep.Sweepable, 0) var errs *multierror.Error - err = conn.ListSnapshotsPagesWithContext(ctx, input, func(page *redshiftserverless.ListSnapshotsOutput, lastPage bool) bool { - if len(page.Snapshots) == 0 { - log.Print("[DEBUG] No Redshift Serverless Snapshots to sweep") - return !lastPage + pages := redshiftserverless.NewListSnapshotsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + errs = multierror.Append(errs, fmt.Errorf("error describing Redshift Serverless Snapshots: %w", err)) } for _, workgroup := range page.Snapshots { r := resourceSnapshot() d := r.Data(nil) - d.SetId(aws.StringValue(workgroup.SnapshotName)) + d.SetId(aws.ToString(workgroup.SnapshotName)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if err != nil { - errs = multierror.Append(errs, fmt.Errorf("error describing Redshift Serverless Snapshots: %w", err)) } if err = sweep.SweepOrchestrator(ctx, sweepResources); err != nil { errs = multierror.Append(errs, fmt.Errorf("error sweeping Redshift Serverless Snapshots for %s: %w", region, err)) } - if awsv1.SkipSweepError(errs.ErrorOrNil()) { + if awsv2.SkipSweepError(errs.ErrorOrNil()) { log.Printf("[WARN] Skipping Redshift Serverless Snapshots sweep for %s: %s", region, errs) return nil } From 25173f7b5987831700675e106e343fd62151e376 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 19:35:34 +0200 Subject: [PATCH 12/14] chore: remove unused files --- internal/service/redshiftserverless/find.go | 139 ------------------ internal/service/redshiftserverless/status.go | 61 -------- internal/service/redshiftserverless/wait.go | 133 ----------------- 3 files changed, 333 deletions(-) delete mode 100644 internal/service/redshiftserverless/find.go delete mode 100644 internal/service/redshiftserverless/status.go delete mode 100644 internal/service/redshiftserverless/wait.go diff --git a/internal/service/redshiftserverless/find.go b/internal/service/redshiftserverless/find.go deleted file mode 100644 index 3923f9d67a6f..000000000000 --- a/internal/service/redshiftserverless/find.go +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package redshiftserverless - -import ( - "context" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -) - -func findNamespaceByName(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.Namespace, error) { - input := &redshiftserverless.GetNamespaceInput{ - NamespaceName: aws.String(name), - } - - output, err := conn.GetNamespaceWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, redshiftserverless.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.Namespace, nil -} - -func findEndpointAccessByName(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.EndpointAccess, error) { - input := &redshiftserverless.GetEndpointAccessInput{ - EndpointName: aws.String(name), - } - - output, err := conn.GetEndpointAccessWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, redshiftserverless.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.Endpoint, nil -} - -func findUsageLimitByName(ctx context.Context, conn *redshiftserverless.RedshiftServerless, id string) (*redshiftserverless.UsageLimit, error) { - input := &redshiftserverless.GetUsageLimitInput{ - UsageLimitId: aws.String(id), - } - - output, err := conn.GetUsageLimitWithContext(ctx, input) - - if tfawserr.ErrMessageContains(err, redshiftserverless.ErrCodeValidationException, "does not exist") { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output.UsageLimit, nil -} - -func findSnapshotByName(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.Snapshot, error) { - input := &redshiftserverless.GetSnapshotInput{ - SnapshotName: aws.String(name), - } - - output, err := conn.GetSnapshotWithContext(ctx, input) - - if tfawserr.ErrMessageContains(err, redshiftserverless.ErrCodeResourceNotFoundException, "snapshot") { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output.Snapshot, nil -} - -func findResourcePolicyByARN(ctx context.Context, conn *redshiftserverless.RedshiftServerless, arn string) (*redshiftserverless.ResourcePolicy, error) { - input := &redshiftserverless.GetResourcePolicyInput{ - ResourceArn: aws.String(arn), - } - - output, err := conn.GetResourcePolicyWithContext(ctx, input) - - if tfawserr.ErrMessageContains(err, redshiftserverless.ErrCodeResourceNotFoundException, "does not exist") { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if output == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - return output.ResourcePolicy, nil -} diff --git a/internal/service/redshiftserverless/status.go b/internal/service/redshiftserverless/status.go deleted file mode 100644 index ca25bb21e74b..000000000000 --- a/internal/service/redshiftserverless/status.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package redshiftserverless - -import ( - "context" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -) - -func statusNamespace(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - output, err := findNamespaceByName(ctx, conn, name) - - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - return output, aws.StringValue(output.Status), nil - } -} - -func statusEndpointAccess(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - output, err := findEndpointAccessByName(ctx, conn, name) - - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - return output, aws.StringValue(output.EndpointStatus), nil - } -} - -func statusSnapshot(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - output, err := findSnapshotByName(ctx, conn, name) - - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - return output, aws.StringValue(output.Status), nil - } -} diff --git a/internal/service/redshiftserverless/wait.go b/internal/service/redshiftserverless/wait.go deleted file mode 100644 index 71d972d74573..000000000000 --- a/internal/service/redshiftserverless/wait.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package redshiftserverless - -import ( - "context" - "time" - - "github.com/aws/aws-sdk-go/service/redshiftserverless" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" -) - -func waitNamespaceDeleted(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.Namespace, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{ - redshiftserverless.NamespaceStatusDeleting, - }, - Target: []string{}, - Refresh: statusNamespace(ctx, conn, name), - Timeout: 10 * time.Minute, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*redshiftserverless.Namespace); ok { - return output, err - } - - return nil, err -} - -func waitNamespaceUpdated(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.Namespace, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{ - redshiftserverless.NamespaceStatusModifying, - }, - Target: []string{ - redshiftserverless.NamespaceStatusAvailable, - }, - Refresh: statusNamespace(ctx, conn, name), - Timeout: 10 * time.Minute, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*redshiftserverless.Namespace); ok { - return output, err - } - - return nil, err -} - -func waitEndpointAccessActive(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.EndpointAccess, error) { //nolint:unparam - stateConf := &retry.StateChangeConf{ - Pending: []string{ - "CREATING", - "MODIFYING", - }, - Target: []string{ - "ACTIVE", - }, - Refresh: statusEndpointAccess(ctx, conn, name), - Timeout: 10 * time.Minute, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*redshiftserverless.EndpointAccess); ok { - return output, err - } - - return nil, err -} - -func waitEndpointAccessDeleted(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.EndpointAccess, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{ - "DELETING", - }, - Target: []string{}, - Refresh: statusEndpointAccess(ctx, conn, name), - Timeout: 10 * time.Minute, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*redshiftserverless.EndpointAccess); ok { - return output, err - } - - return nil, err -} - -func waitSnapshotAvailable(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.Snapshot, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{ - redshiftserverless.SnapshotStatusCreating, - }, - Target: []string{ - redshiftserverless.SnapshotStatusAvailable, - }, - Refresh: statusSnapshot(ctx, conn, name), - Timeout: 10 * time.Minute, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*redshiftserverless.Snapshot); ok { - return output, err - } - - return nil, err -} - -func waitSnapshotDeleted(ctx context.Context, conn *redshiftserverless.RedshiftServerless, name string) (*redshiftserverless.Snapshot, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{ - redshiftserverless.SnapshotStatusAvailable, - }, - Target: []string{}, - Refresh: statusSnapshot(ctx, conn, name), - Timeout: 10 * time.Minute, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*redshiftserverless.Snapshot); ok { - return output, err - } - - return nil, err -} From 4f257d11bf2c7cf7e827fbb9f1afc26342d4b87b Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 20:13:05 +0200 Subject: [PATCH 13/14] chore: add timeout consts --- internal/service/redshiftserverless/namespace.go | 12 ++++++++---- internal/service/redshiftserverless/workgroup.go | 6 +++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/internal/service/redshiftserverless/namespace.go b/internal/service/redshiftserverless/namespace.go index 46faee745ec9..e63cfa6050f8 100644 --- a/internal/service/redshiftserverless/namespace.go +++ b/internal/service/redshiftserverless/namespace.go @@ -269,7 +269,7 @@ func resourceNamespaceDelete(ctx context.Context, d *schema.ResourceData, meta i conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Namespace: %s", d.Id()) - _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.ConflictException](ctx, 10*time.Minute, + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.ConflictException](ctx, namespaceDeletedTimeout, func() (interface{}, error) { return conn.DeleteNamespace(ctx, &redshiftserverless.DeleteNamespaceInput{ NamespaceName: aws.String(d.Id()), @@ -293,6 +293,11 @@ func resourceNamespaceDelete(ctx context.Context, d *schema.ResourceData, meta i return diags } +const ( + namespaceDeletedTimeout = 10 * time.Minute + namespaceUpdatedTimeout = 10 * time.Minute +) + func findNamespaceByName(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Namespace, error) { input := &redshiftserverless.GetNamespaceInput{ NamespaceName: aws.String(name), @@ -339,7 +344,7 @@ func waitNamespaceDeleted(ctx context.Context, conn *redshiftserverless.Client, Pending: enum.Slice(awstypes.NamespaceStatusDeleting), Target: []string{}, Refresh: statusNamespace(ctx, conn, name), - Timeout: 10 * time.Minute, + Timeout: namespaceDeletedTimeout, } outputRaw, err := stateConf.WaitForStateContext(ctx) @@ -356,7 +361,7 @@ func waitNamespaceUpdated(ctx context.Context, conn *redshiftserverless.Client, Pending: enum.Slice(awstypes.NamespaceStatusModifying), Target: enum.Slice(awstypes.NamespaceStatusAvailable), Refresh: statusNamespace(ctx, conn, name), - Timeout: 10 * time.Minute, + Timeout: namespaceUpdatedTimeout, } outputRaw, err := stateConf.WaitForStateContext(ctx) @@ -376,7 +381,6 @@ func flattenNamespaceIAMRoles(iamRoles []string) []string { var tfList []string for _, iamRole := range iamRoles { - if arn.IsARN(iamRole) { tfList = append(tfList, iamRole) continue diff --git a/internal/service/redshiftserverless/workgroup.go b/internal/service/redshiftserverless/workgroup.go index 5020407ce42a..9d97a7469a6c 100644 --- a/internal/service/redshiftserverless/workgroup.go +++ b/internal/service/redshiftserverless/workgroup.go @@ -450,7 +450,7 @@ func resourceWorkgroupDelete(ctx context.Context, d *schema.ResourceData, meta i conn := meta.(*conns.AWSClient).RedshiftServerlessClient(ctx) log.Printf("[DEBUG] Deleting Redshift Serverless Workgroup: %s", d.Id()) - _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.ConflictException](ctx, 10*time.Minute, + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.ConflictException](ctx, workgroupDeletedTimeout, func() (interface{}, error) { return conn.DeleteWorkgroup(ctx, &redshiftserverless.DeleteWorkgroupInput{ WorkgroupName: aws.String(d.Id()), @@ -489,6 +489,10 @@ func updateWorkgroup(ctx context.Context, conn *redshiftserverless.Client, input return nil } +const ( + workgroupDeletedTimeout = 10 * time.Minute +) + func findWorkgroupByName(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Workgroup, error) { input := &redshiftserverless.GetWorkgroupInput{ WorkgroupName: aws.String(name), From 20ba3364226f2701783af0d9420ec66c739a4dd6 Mon Sep 17 00:00:00 2001 From: Daniel Rieske Date: Tue, 13 Aug 2024 21:53:06 +0200 Subject: [PATCH 14/14] fix: `TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible` you need a snapshot to be able to update the capacity. During the creation of this `conflictExceptions` occur. We already retry on the deletion for it so it makes sense for update aswell. make testacc TESTARGS='-run=TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible' PKG=redshiftserverless make: Verifying source code with gofmt... ==> Checking that code complies with gofmt requirements... TF_ACC=1 go1.22.6 test ./internal/service/redshiftserverless/... -v -count 1 -parallel 20 -run=TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible -timeout 360m === RUN TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible === PAUSE TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible === CONT TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible --- PASS: TestAccRedshiftServerlessWorkgroup_baseAndMaxCapacityAndPubliclyAccessible (2002.95s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/redshiftserverless 2007.594s --- internal/service/redshiftserverless/workgroup.go | 9 ++++++++- internal/service/redshiftserverless/workgroup_test.go | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/service/redshiftserverless/workgroup.go b/internal/service/redshiftserverless/workgroup.go index 9d97a7469a6c..bc5849561a70 100644 --- a/internal/service/redshiftserverless/workgroup.go +++ b/internal/service/redshiftserverless/workgroup.go @@ -475,8 +475,14 @@ func resourceWorkgroupDelete(ctx context.Context, d *schema.ResourceData, meta i } func updateWorkgroup(ctx context.Context, conn *redshiftserverless.Client, input *redshiftserverless.UpdateWorkgroupInput, timeout time.Duration) error { + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.ConflictException](ctx, workgroupUpdatedTimeout, + func() (interface{}, error) { + return conn.UpdateWorkgroup(ctx, input) + }, + // "ConflictException: There is an operation running on the workgroup. Try to update it later." + "operation running") + name := aws.ToString(input.WorkgroupName) - _, err := conn.UpdateWorkgroup(ctx, input) if err != nil { return fmt.Errorf("updating Redshift Serverless Workgroup (%s): %w", name, err) @@ -491,6 +497,7 @@ func updateWorkgroup(ctx context.Context, conn *redshiftserverless.Client, input const ( workgroupDeletedTimeout = 10 * time.Minute + workgroupUpdatedTimeout = 10 * time.Minute ) func findWorkgroupByName(ctx context.Context, conn *redshiftserverless.Client, name string) (*awstypes.Workgroup, error) { diff --git a/internal/service/redshiftserverless/workgroup_test.go b/internal/service/redshiftserverless/workgroup_test.go index 446dbe57c0ac..ec436c49c748 100644 --- a/internal/service/redshiftserverless/workgroup_test.go +++ b/internal/service/redshiftserverless/workgroup_test.go @@ -403,6 +403,12 @@ resource "aws_redshiftserverless_workgroup" "test" { workgroup_name = %[1]q base_capacity = %[2]d } + +resource "aws_redshiftserverless_snapshot" "test" { + namespace_name = aws_redshiftserverless_workgroup.test.namespace_name + snapshot_name = %[1]q + retention_period = 10 +} `, rName, baseCapacity) }