Skip to content

Commit

Permalink
r/aws_s3control_multi_region_access_point & r/aws_s3control_multi_reg…
Browse files Browse the repository at this point in the history
…ion_access_point_policy: Switch to 'WithoutTimeout' CRUD handlers (#15090).

Acceptance test output:

% make testacc TESTARGS='-run=TestAccS3ControlMultiRegionAccessPoint' PKG=s3control ACCTEST_PARALLELISM=3
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./internal/service/s3control/... -v -count 1 -parallel 3  -run=TestAccS3ControlMultiRegionAccessPoint -timeout 180m
=== RUN   TestAccS3ControlMultiRegionAccessPointDataSource_basic
=== PAUSE TestAccS3ControlMultiRegionAccessPointDataSource_basic
=== RUN   TestAccS3ControlMultiRegionAccessPointPolicy_basic
=== PAUSE TestAccS3ControlMultiRegionAccessPointPolicy_basic
=== RUN   TestAccS3ControlMultiRegionAccessPointPolicy_disappears_MultiRegionAccessPoint
=== PAUSE TestAccS3ControlMultiRegionAccessPointPolicy_disappears_MultiRegionAccessPoint
=== RUN   TestAccS3ControlMultiRegionAccessPointPolicy_details_policy
=== PAUSE TestAccS3ControlMultiRegionAccessPointPolicy_details_policy
=== RUN   TestAccS3ControlMultiRegionAccessPointPolicy_details_name
=== PAUSE TestAccS3ControlMultiRegionAccessPointPolicy_details_name
=== RUN   TestAccS3ControlMultiRegionAccessPoint_basic
=== PAUSE TestAccS3ControlMultiRegionAccessPoint_basic
=== RUN   TestAccS3ControlMultiRegionAccessPoint_disappears
=== PAUSE TestAccS3ControlMultiRegionAccessPoint_disappears
=== RUN   TestAccS3ControlMultiRegionAccessPoint_PublicAccessBlock
=== PAUSE TestAccS3ControlMultiRegionAccessPoint_PublicAccessBlock
=== RUN   TestAccS3ControlMultiRegionAccessPoint_name
=== PAUSE TestAccS3ControlMultiRegionAccessPoint_name
=== RUN   TestAccS3ControlMultiRegionAccessPoint_threeRegions
=== PAUSE TestAccS3ControlMultiRegionAccessPoint_threeRegions
=== CONT  TestAccS3ControlMultiRegionAccessPointDataSource_basic
=== CONT  TestAccS3ControlMultiRegionAccessPoint_basic
=== CONT  TestAccS3ControlMultiRegionAccessPoint_threeRegions
--- PASS: TestAccS3ControlMultiRegionAccessPoint_basic (336.67s)
=== CONT  TestAccS3ControlMultiRegionAccessPoint_name
--- PASS: TestAccS3ControlMultiRegionAccessPoint_threeRegions (348.44s)
=== CONT  TestAccS3ControlMultiRegionAccessPoint_PublicAccessBlock
--- PASS: TestAccS3ControlMultiRegionAccessPointDataSource_basic (359.54s)
=== CONT  TestAccS3ControlMultiRegionAccessPoint_disappears
--- PASS: TestAccS3ControlMultiRegionAccessPoint_disappears (256.99s)
=== CONT  TestAccS3ControlMultiRegionAccessPointPolicy_details_policy
--- PASS: TestAccS3ControlMultiRegionAccessPoint_PublicAccessBlock (333.59s)
=== CONT  TestAccS3ControlMultiRegionAccessPointPolicy_details_name
--- PASS: TestAccS3ControlMultiRegionAccessPointPolicy_details_policy (265.17s)
=== CONT  TestAccS3ControlMultiRegionAccessPointPolicy_disappears_MultiRegionAccessPoint
--- PASS: TestAccS3ControlMultiRegionAccessPoint_name (587.22s)
=== CONT  TestAccS3ControlMultiRegionAccessPointPolicy_basic
--- PASS: TestAccS3ControlMultiRegionAccessPointPolicy_disappears_MultiRegionAccessPoint (262.98s)
--- PASS: TestAccS3ControlMultiRegionAccessPointPolicy_details_name (526.15s)
--- PASS: TestAccS3ControlMultiRegionAccessPointPolicy_basic (286.04s)
PASS
ok  	github.com/hashicorp/terraform-provider-aws/internal/service/s3control	1215.420s
  • Loading branch information
ewbankkit committed Dec 23, 2022
1 parent 9c13138 commit 723aae3
Show file tree
Hide file tree
Showing 12 changed files with 232 additions and 265 deletions.
4 changes: 0 additions & 4 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -870,8 +870,6 @@ func New(ctx context.Context) (*schema.Provider, error) {
"aws_s3_bucket_objects": s3.DataSourceBucketObjects(), // DEPRECATED: use aws_s3_objects instead
"aws_s3_bucket_policy": s3.DataSourceBucketPolicy(),

"aws_s3control_multi_region_access_point": s3control.DataSourceMultiRegionAccessPoint(),

"aws_sagemaker_prebuilt_ecr_image": sagemaker.DataSourcePrebuiltECRImage(),

"aws_secretsmanager_random_password": secretsmanager.DataSourceRandomPassword(),
Expand Down Expand Up @@ -2005,8 +2003,6 @@ func New(ctx context.Context) (*schema.Provider, error) {
"aws_s3_object_copy": s3.ResourceObjectCopy(),
"aws_s3_bucket_object": s3.ResourceBucketObject(), // DEPRECATED: use aws_s3_object instead

"aws_s3control_multi_region_access_point": s3control.ResourceMultiRegionAccessPoint(),
"aws_s3control_multi_region_access_point_policy": s3control.ResourceMultiRegionAccessPointPolicy(),
"aws_s3control_object_lambda_access_point": s3control.ResourceObjectLambdaAccessPoint(),
"aws_s3control_object_lambda_access_point_policy": s3control.ResourceObjectLambdaAccessPointPolicy(),

Expand Down
2 changes: 2 additions & 0 deletions internal/service/s3control/exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ var (
ResourceBucket = resourceBucket
ResourceBucketLifecycleConfiguration = resourceBucketLifecycleConfiguration
ResourceBucketPolicy = resourceBucketPolicy
ResourceMultiRegionAccessPoint = resourceMultiRegionAccessPoint
ResourceMultiRegionAccessPointPolicy = resourceMultiRegionAccessPointPolicy
ResourceStorageLensConfiguration = resourceStorageLensConfiguration
)
78 changes: 0 additions & 78 deletions internal/service/s3control/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,84 +8,6 @@ import (
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func FindMultiRegionAccessPointByAccountIDAndName(conn *s3control.S3Control, accountID string, name string) (*s3control.MultiRegionAccessPointReport, error) {
input := &s3control.GetMultiRegionAccessPointInput{
AccountId: aws.String(accountID),
Name: aws.String(name),
}

output, err := conn.GetMultiRegionAccessPoint(input)

if tfawserr.ErrCodeEquals(err, errCodeNoSuchMultiRegionAccessPoint) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.AccessPoint == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.AccessPoint, nil
}

func findMultiRegionAccessPointOperationByAccountIDAndTokenARN(conn *s3control.S3Control, accountID string, requestTokenARN string) (*s3control.AsyncOperation, error) {
input := &s3control.DescribeMultiRegionAccessPointOperationInput{
AccountId: aws.String(accountID),
RequestTokenARN: aws.String(requestTokenARN),
}

output, err := conn.DescribeMultiRegionAccessPointOperation(input)

if tfawserr.ErrCodeEquals(err, errCodeNoSuchAsyncRequest) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.AsyncOperation == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.AsyncOperation, nil
}

func FindMultiRegionAccessPointPolicyDocumentByAccountIDAndName(conn *s3control.S3Control, accountID string, name string) (*s3control.MultiRegionAccessPointPolicyDocument, error) {
input := &s3control.GetMultiRegionAccessPointPolicyInput{
AccountId: aws.String(accountID),
Name: aws.String(name),
}

output, err := conn.GetMultiRegionAccessPointPolicy(input)

if tfawserr.ErrCodeEquals(err, errCodeNoSuchMultiRegionAccessPoint) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.Policy == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.Policy, nil
}

func FindObjectLambdaAccessPointByAccountIDAndName(conn *s3control.S3Control, accountID string, name string) (*s3control.ObjectLambdaConfiguration, error) {
input := &s3control.GetAccessPointConfigurationForObjectLambdaInput{
AccountId: aws.String(accountID),
Expand Down
163 changes: 137 additions & 26 deletions internal/service/s3control/multi_region_access_point.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package s3control

import (
"context"
"fmt"
"log"
"strings"
Expand All @@ -11,18 +12,24 @@ import (
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/service/s3control"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"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/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func ResourceMultiRegionAccessPoint() *schema.Resource {
func init() {
_sp.registerSDKResourceFactory("aws_s3control_multi_region_access_point", resourceMultiRegionAccessPoint)
}

func resourceMultiRegionAccessPoint() *schema.Resource {
return &schema.Resource{
Create: resourceMultiRegionAccessPointCreate,
Read: resourceMultiRegionAccessPointRead,
Delete: resourceMultiRegionAccessPointDelete,
CreateWithoutTimeout: resourceMultiRegionAccessPointCreate,
ReadWithoutTimeout: resourceMultiRegionAccessPointRead,
DeleteWithoutTimeout: resourceMultiRegionAccessPointDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
Expand Down Expand Up @@ -131,11 +138,11 @@ func ResourceMultiRegionAccessPoint() *schema.Resource {
}
}

func resourceMultiRegionAccessPointCreate(d *schema.ResourceData, meta interface{}) error {
func resourceMultiRegionAccessPointCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn, err := ConnForMRAP(meta.(*conns.AWSClient))

if err != nil {
return err
return diag.FromErr(err)
}

accountID := meta.(*conns.AWSClient).AccountID
Expand All @@ -153,38 +160,37 @@ func resourceMultiRegionAccessPointCreate(d *schema.ResourceData, meta interface

resourceID := MultiRegionAccessPointCreateResourceID(accountID, aws.StringValue(input.Details.Name))

log.Printf("[DEBUG] Creating S3 Multi-Region Access Point: %s", input)
output, err := conn.CreateMultiRegionAccessPoint(input)
output, err := conn.CreateMultiRegionAccessPointWithContext(ctx, input)

if err != nil {
return fmt.Errorf("error creating S3 Multi-Region Access Point (%s): %w", resourceID, err)
return diag.Errorf("creating S3 Multi-Region Access Point (%s): %s", resourceID, err)
}

d.SetId(resourceID)

_, err = waitMultiRegionAccessPointRequestSucceeded(conn, accountID, aws.StringValue(output.RequestTokenARN), d.Timeout(schema.TimeoutCreate))
_, err = waitMultiRegionAccessPointRequestSucceeded(ctx, conn, accountID, aws.StringValue(output.RequestTokenARN), d.Timeout(schema.TimeoutCreate))

if err != nil {
return fmt.Errorf("error waiting for Multi-Region Access Point (%s) create: %s", d.Id(), err)
return diag.Errorf("waiting for Multi-Region Access Point (%s) create: %s", d.Id(), err)
}

return resourceMultiRegionAccessPointRead(d, meta)
return resourceMultiRegionAccessPointRead(ctx, d, meta)
}

func resourceMultiRegionAccessPointRead(d *schema.ResourceData, meta interface{}) error {
func resourceMultiRegionAccessPointRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn, err := ConnForMRAP(meta.(*conns.AWSClient))

if err != nil {
return err
return diag.FromErr(err)
}

accountID, name, err := MultiRegionAccessPointParseResourceID(d.Id())

if err != nil {
return err
return diag.FromErr(err)
}

accessPoint, err := FindMultiRegionAccessPointByAccountIDAndName(conn, accountID, name)
accessPoint, err := FindMultiRegionAccessPointByTwoPartKey(ctx, conn, accountID, name)

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] S3 Multi-Region Access Point (%s) not found, removing from state", d.Id())
Expand All @@ -193,7 +199,7 @@ func resourceMultiRegionAccessPointRead(d *schema.ResourceData, meta interface{}
}

if err != nil {
return fmt.Errorf("error reading S3 Multi-Region Access Point (%s): %w", d.Id(), err)
return diag.Errorf("reading S3 Multi-Region Access Point (%s): %s", d.Id(), err)
}

alias := aws.StringValue(accessPoint.Alias)
Expand All @@ -207,7 +213,7 @@ func resourceMultiRegionAccessPointRead(d *schema.ResourceData, meta interface{}
d.Set("alias", alias)
d.Set("arn", arn)
if err := d.Set("details", []interface{}{flattenMultiRegionAccessPointReport(accessPoint)}); err != nil {
return fmt.Errorf("error setting details: %w", err)
return diag.Errorf("setting details: %s", err)
}
// https://docs.aws.amazon.com/AmazonS3/latest/userguide//MultiRegionAccessPointRequests.html#MultiRegionAccessPointHostnames.
d.Set("domain_name", meta.(*conns.AWSClient).PartitionHostname(fmt.Sprintf("%s.accesspoint.s3-global", alias)))
Expand All @@ -216,21 +222,21 @@ func resourceMultiRegionAccessPointRead(d *schema.ResourceData, meta interface{}
return nil
}

func resourceMultiRegionAccessPointDelete(d *schema.ResourceData, meta interface{}) error {
func resourceMultiRegionAccessPointDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn, err := ConnForMRAP(meta.(*conns.AWSClient))

if err != nil {
return err
return diag.FromErr(err)
}

accountID, name, err := MultiRegionAccessPointParseResourceID(d.Id())

if err != nil {
return err
return diag.FromErr(err)
}

log.Printf("[DEBUG] Deleting S3 Multi-Region Access Point: %s", d.Id())
output, err := conn.DeleteMultiRegionAccessPoint(&s3control.DeleteMultiRegionAccessPointInput{
output, err := conn.DeleteMultiRegionAccessPointWithContext(ctx, &s3control.DeleteMultiRegionAccessPointInput{
AccountId: aws.String(accountID),
Details: &s3control.DeleteMultiRegionAccessPointInput_{
Name: aws.String(name),
Expand All @@ -242,13 +248,13 @@ func resourceMultiRegionAccessPointDelete(d *schema.ResourceData, meta interface
}

if err != nil {
return fmt.Errorf("error deleting S3 Multi-Region Access Point (%s): %w", d.Id(), err)
return diag.Errorf("deleting S3 Multi-Region Access Point (%s): %s", d.Id(), err)
}

_, err = waitMultiRegionAccessPointRequestSucceeded(conn, accountID, aws.StringValue(output.RequestTokenARN), d.Timeout(schema.TimeoutDelete))
_, err = waitMultiRegionAccessPointRequestSucceeded(ctx, conn, accountID, aws.StringValue(output.RequestTokenARN), d.Timeout(schema.TimeoutDelete))

if err != nil {
return fmt.Errorf("error waiting for S3 Multi-Region Access Point (%s) delete: %w", d.Id(), err)
return diag.Errorf("error waiting for S3 Multi-Region Access Point (%s) delete: %s", d.Id(), err)
}

return nil
Expand All @@ -266,12 +272,117 @@ func ConnForMRAP(client *conns.AWSClient) (*s3control.S3Control, error) {
sess, err := conns.NewSessionForRegion(&originalConn.Config, region, client.TerraformVersion)

if err != nil {
return nil, fmt.Errorf("error creating AWS session: %w", err)
return nil, fmt.Errorf("creating AWS session: %w", err)
}

return s3control.New(sess), nil
}

func FindMultiRegionAccessPointByTwoPartKey(ctx context.Context, conn *s3control.S3Control, accountID string, name string) (*s3control.MultiRegionAccessPointReport, error) {
input := &s3control.GetMultiRegionAccessPointInput{
AccountId: aws.String(accountID),
Name: aws.String(name),
}

output, err := conn.GetMultiRegionAccessPointWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, errCodeNoSuchMultiRegionAccessPoint) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.AccessPoint == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.AccessPoint, nil
}

func findMultiRegionAccessPointOperationByAccountIDAndTokenARN(ctx context.Context, conn *s3control.S3Control, accountID string, requestTokenARN string) (*s3control.AsyncOperation, error) {
input := &s3control.DescribeMultiRegionAccessPointOperationInput{
AccountId: aws.String(accountID),
RequestTokenARN: aws.String(requestTokenARN),
}

output, err := conn.DescribeMultiRegionAccessPointOperationWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, errCodeNoSuchAsyncRequest) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.AsyncOperation == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return output.AsyncOperation, nil
}

func statusMultiRegionAccessPointRequest(ctx context.Context, conn *s3control.S3Control, accountID string, requestTokenARN string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := findMultiRegionAccessPointOperationByAccountIDAndTokenARN(ctx, conn, accountID, requestTokenARN)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, aws.StringValue(output.RequestStatus), nil
}
}

const (
// Minimum amount of times to verify change propagation
propagationContinuousTargetOccurence = 2

// Minimum amount of time to wait between S3control change polls
propagationMinTimeout = 5 * time.Second

// Maximum amount of time to wait for S3control changes to propagate
propagationTimeout = 1 * time.Minute

multiRegionAccessPointRequestSucceededMinTimeout = 5 * time.Second

multiRegionAccessPointRequestSucceededDelay = 15 * time.Second
)

func waitMultiRegionAccessPointRequestSucceeded(ctx context.Context, conn *s3control.S3Control, accountID string, requestTokenArn string, timeout time.Duration) (*s3control.AsyncOperation, error) { //nolint:unparam
stateConf := &resource.StateChangeConf{
Target: []string{RequestStatusSucceeded},
Timeout: timeout,
Refresh: statusMultiRegionAccessPointRequest(ctx, conn, accountID, requestTokenArn),
MinTimeout: multiRegionAccessPointRequestSucceededMinTimeout,
Delay: multiRegionAccessPointRequestSucceededDelay,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*s3control.AsyncOperation); ok {
if status, responseDetails := aws.StringValue(output.RequestStatus), output.ResponseDetails; status == RequestStatusFailed && responseDetails != nil && responseDetails.ErrorDetails != nil {
tfresource.SetLastError(err, fmt.Errorf("%s: %s", aws.StringValue(responseDetails.ErrorDetails.Code), aws.StringValue(responseDetails.ErrorDetails.Message)))
}

return output, err
}

return nil, err
}

const multiRegionAccessPointResourceIDSeparator = ":"

func MultiRegionAccessPointCreateResourceID(accountID, accessPointName string) string {
Expand Down
Loading

0 comments on commit 723aae3

Please sign in to comment.