Skip to content

Commit

Permalink
r/aws_s3_account_public_access_block & d/aws_s3_account_public_access…
Browse files Browse the repository at this point in the history
…_block: Switch to 'WithoutTimeout' CRUD handlers (#15090).

Acceptance test output:

% make testacc TESTARGS='-run=TestAccS3ControlAccountPublicAccessBlock_serial' 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=TestAccS3ControlAccountPublicAccessBlock_serial -timeout 180m
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/IgnorePublicAcls
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/RestrictPublicBuckets
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/DataSourceBasic
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/basic
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/disappears
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/AccountId
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/BlockPublicAcls
=== RUN   TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/BlockPublicPolicy
--- PASS: TestAccS3ControlAccountPublicAccessBlock_serial (281.95s)
    --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock (281.95s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/IgnorePublicAcls (53.59s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/RestrictPublicBuckets (51.64s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/DataSourceBasic (17.86s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/basic (20.37s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/disappears (16.18s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/AccountId (20.41s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/BlockPublicAcls (51.20s)
        --- PASS: TestAccS3ControlAccountPublicAccessBlock_serial/PublicAccessBlock/BlockPublicPolicy (50.69s)
PASS
ok  	github.com/hashicorp/terraform-provider-aws/internal/service/s3control	286.966s
  • Loading branch information
ewbankkit committed Dec 22, 2022
1 parent 96e76b3 commit 6f101c4
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 377 deletions.
2 changes: 0 additions & 2 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +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_s3_account_public_access_block": s3control.DataSourceAccountPublicAccessBlock(),
"aws_s3control_multi_region_access_point": s3control.DataSourceMultiRegionAccessPoint(),

"aws_sagemaker_prebuilt_ecr_image": sagemaker.DataSourcePrebuiltECRImage(),
Expand Down Expand Up @@ -2006,7 +2005,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_s3_account_public_access_block": s3control.ResourceAccountPublicAccessBlock(),
"aws_s3control_bucket": s3control.ResourceBucket(),
"aws_s3control_bucket_lifecycle_configuration": s3control.ResourceBucketLifecycleConfiguration(),
"aws_s3control_bucket_policy": s3control.ResourceBucketPolicy(),
Expand Down
1 change: 1 addition & 0 deletions internal/service/s3control/access_point_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ func testAccCheckAccessPointDestroy(s *terraform.State) error {

return fmt.Errorf("S3 Access Point %s still exists", rs.Primary.ID)
}

return nil
}

Expand Down
193 changes: 111 additions & 82 deletions internal/service/s3control/account_public_access_block.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
package s3control

import (
"fmt"
"context"
"log"
"reflect"
"strconv"

"github.com/aws/aws-sdk-go/aws"
"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-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func ResourceAccountPublicAccessBlock() *schema.Resource {
func init() {
_sp.registerSDKResourceFactory("aws_s3_account_public_access_block", resourceAccountPublicAccessBlock)
}

func resourceAccountPublicAccessBlock() *schema.Resource {
return &schema.Resource{
Create: resourceAccountPublicAccessBlockCreate,
Read: resourceAccountPublicAccessBlockRead,
Update: resourceAccountPublicAccessBlockUpdate,
Delete: resourceAccountPublicAccessBlockDelete,
CreateWithoutTimeout: resourceAccountPublicAccessBlockCreate,
ReadWithoutTimeout: resourceAccountPublicAccessBlockRead,
UpdateWithoutTimeout: resourceAccountPublicAccessBlockUpdate,
DeleteWithoutTimeout: resourceAccountPublicAccessBlockDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Expand Down Expand Up @@ -56,7 +64,7 @@ func ResourceAccountPublicAccessBlock() *schema.Resource {
}
}

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

accountID := meta.(*conns.AWSClient).AccountID
Expand All @@ -74,130 +82,151 @@ func resourceAccountPublicAccessBlockCreate(d *schema.ResourceData, meta interfa
},
}

log.Printf("[DEBUG] Creating S3 Account Public Access Block: %s", input)
_, err := conn.PutPublicAccessBlock(input)
_, err := conn.PutPublicAccessBlockWithContext(ctx, input)

if err != nil {
return fmt.Errorf("error creating S3 Account Public Access Block: %s", err)
return diag.Errorf("creating S3 Account Public Access Block (%s): %s", accountID, err)
}

d.SetId(accountID)

return resourceAccountPublicAccessBlockRead(d, meta)
}

func resourceAccountPublicAccessBlockRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).S3ControlConn()
_, err = tfresource.RetryWhenNotFoundContext(ctx, propagationTimeout, func() (interface{}, error) {
return FindPublicAccessBlockByAccountID(ctx, conn, d.Id())
})

input := &s3control.GetPublicAccessBlockInput{
AccountId: aws.String(d.Id()),
if err != nil {
return diag.Errorf("waiting for S3 Account Public Access Block (%s) create: %s", d.Id(), err)
}

// Retry for eventual consistency on creation
var output *s3control.GetPublicAccessBlockOutput
err := resource.Retry(propagationTimeout, func() *resource.RetryError {
var err error
output, err = conn.GetPublicAccessBlock(input)

if d.IsNewResource() && tfawserr.ErrCodeEquals(err, s3control.ErrCodeNoSuchPublicAccessBlockConfiguration) {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}
return resourceAccountPublicAccessBlockRead(ctx, d, meta)
}

return nil
})
func resourceAccountPublicAccessBlockRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).S3ControlConn()

if tfresource.TimedOut(err) {
output, err = conn.GetPublicAccessBlock(input)
}
output, err := FindPublicAccessBlockByAccountID(ctx, conn, d.Id())

if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, s3control.ErrCodeNoSuchPublicAccessBlockConfiguration) {
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] S3 Account Public Access Block (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("error reading S3 Account Public Access Block: %s", err)
}

if output == nil || output.PublicAccessBlockConfiguration == nil {
return fmt.Errorf("error reading S3 Account Public Access Block (%s): missing public access block configuration", d.Id())
return diag.Errorf("reading S3 Account Public Access Block (%s): %s", d.Id(), err)
}

d.Set("account_id", d.Id())
d.Set("block_public_acls", output.PublicAccessBlockConfiguration.BlockPublicAcls)
d.Set("block_public_policy", output.PublicAccessBlockConfiguration.BlockPublicPolicy)
d.Set("ignore_public_acls", output.PublicAccessBlockConfiguration.IgnorePublicAcls)
d.Set("restrict_public_buckets", output.PublicAccessBlockConfiguration.RestrictPublicBuckets)
d.Set("block_public_acls", output.BlockPublicAcls)
d.Set("block_public_policy", output.BlockPublicPolicy)
d.Set("ignore_public_acls", output.IgnorePublicAcls)
d.Set("restrict_public_buckets", output.RestrictPublicBuckets)

return nil
}

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

publicAccessBlockConfiguration := &s3control.PublicAccessBlockConfiguration{
BlockPublicAcls: aws.Bool(d.Get("block_public_acls").(bool)),
BlockPublicPolicy: aws.Bool(d.Get("block_public_policy").(bool)),
IgnorePublicAcls: aws.Bool(d.Get("ignore_public_acls").(bool)),
RestrictPublicBuckets: aws.Bool(d.Get("restrict_public_buckets").(bool)),
}
input := &s3control.PutPublicAccessBlockInput{
AccountId: aws.String(d.Id()),
PublicAccessBlockConfiguration: publicAccessBlockConfiguration,
}

_, err := conn.PutPublicAccessBlockWithContext(ctx, input)

if err != nil {
return diag.Errorf("updating S3 Account Public Access Block (%s): %s", d.Id(), err)
}

if _, err := waitPublicAccessBlockEqual(ctx, conn, d.Id(), publicAccessBlockConfiguration); err != nil {
return diag.Errorf("waiting for S3 Account Public Access Block (%s) update: %s", d.Id(), err)
}

return resourceAccountPublicAccessBlockRead(ctx, d, meta)
}

func resourceAccountPublicAccessBlockDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).S3ControlConn()

log.Printf("[DEBUG] Deleting S3 Account Public Access Block: %s", d.Id())
_, err := conn.DeletePublicAccessBlockWithContext(ctx, &s3control.DeletePublicAccessBlockInput{
AccountId: aws.String(d.Id()),
PublicAccessBlockConfiguration: &s3control.PublicAccessBlockConfiguration{
BlockPublicAcls: aws.Bool(d.Get("block_public_acls").(bool)),
BlockPublicPolicy: aws.Bool(d.Get("block_public_policy").(bool)),
IgnorePublicAcls: aws.Bool(d.Get("ignore_public_acls").(bool)),
RestrictPublicBuckets: aws.Bool(d.Get("restrict_public_buckets").(bool)),
},
})

if tfawserr.ErrCodeEquals(err, s3control.ErrCodeNoSuchPublicAccessBlockConfiguration) {
return nil
}

log.Printf("[DEBUG] Updating S3 Account Public Access Block: %s", input)
_, err := conn.PutPublicAccessBlock(input)
if err != nil {
return fmt.Errorf("error updating S3 Account Public Access Block (%s): %s", d.Id(), err)
return diag.Errorf("deleting S3 Account Public Access Block (%s): %s", d.Id(), err)
}

if d.HasChange("block_public_acls") {
if _, err := waitPublicAccessBlockConfigurationBlockPublicACLsUpdated(conn, d.Id(), d.Get("block_public_acls").(bool)); err != nil {
return fmt.Errorf("error waiting for S3 Account Public Access Block (%s) block_public_acls update: %w", d.Id(), err)
}
return nil
}

func FindPublicAccessBlockByAccountID(ctx context.Context, conn *s3control.S3Control, accountID string) (*s3control.PublicAccessBlockConfiguration, error) {
input := &s3control.GetPublicAccessBlockInput{
AccountId: aws.String(accountID),
}

if d.HasChange("block_public_policy") {
if _, err := waitPublicAccessBlockConfigurationBlockPublicPolicyUpdated(conn, d.Id(), d.Get("block_public_policy").(bool)); err != nil {
return fmt.Errorf("error waiting for S3 Account Public Access Block (%s) block_public_policy update: %w", d.Id(), err)
output, err := conn.GetPublicAccessBlockWithContext(ctx, input)

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

if d.HasChange("ignore_public_acls") {
if _, err := waitPublicAccessBlockConfigurationIgnorePublicACLsUpdated(conn, d.Id(), d.Get("ignore_public_acls").(bool)); err != nil {
return fmt.Errorf("error waiting for S3 Account Public Access Block (%s) ignore_public_acls update: %w", d.Id(), err)
}
if err != nil {
return nil, err
}

if d.HasChange("restrict_public_buckets") {
if _, err := waitPublicAccessBlockConfigurationRestrictPublicBucketsUpdated(conn, d.Id(), d.Get("restrict_public_buckets").(bool)); err != nil {
return fmt.Errorf("error waiting for S3 Account Public Access Block (%s) restrict_public_buckets update: %w", d.Id(), err)
}
if output == nil || output.PublicAccessBlockConfiguration == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return resourceAccountPublicAccessBlockRead(d, meta)
return output.PublicAccessBlockConfiguration, nil
}

func resourceAccountPublicAccessBlockDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).S3ControlConn()
func statusPublicAccessBlockEqual(ctx context.Context, conn *s3control.S3Control, accountID string, target *s3control.PublicAccessBlockConfiguration) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindPublicAccessBlockByAccountID(ctx, conn, accountID)

input := &s3control.DeletePublicAccessBlockInput{
AccountId: aws.String(d.Id()),
}
if tfresource.NotFound(err) {
return nil, "", nil
}

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

_, err := conn.DeletePublicAccessBlock(input)
return output, strconv.FormatBool(reflect.DeepEqual(output, target)), nil
}
}

if tfawserr.ErrCodeEquals(err, s3control.ErrCodeNoSuchPublicAccessBlockConfiguration) {
return nil
func waitPublicAccessBlockEqual(ctx context.Context, conn *s3control.S3Control, accountID string, target *s3control.PublicAccessBlockConfiguration) (*s3control.PublicAccessBlockConfiguration, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{strconv.FormatBool(false)},
Target: []string{strconv.FormatBool(true)},
Refresh: statusPublicAccessBlockEqual(ctx, conn, accountID, target),
Timeout: propagationTimeout,
MinTimeout: propagationMinTimeout,
ContinuousTargetOccurence: propagationContinuousTargetOccurence,
}

if err != nil {
return fmt.Errorf("error deleting S3 Account Public Access Block (%s): %s", d.Id(), err)
outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*s3control.PublicAccessBlockConfiguration); ok {
return output, err
}

return nil
return nil, err
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ package s3control

import (
"context"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3control"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func DataSourceAccountPublicAccessBlock() *schema.Resource {
func init() {
_sp.registerSDKDataSourceFactory("aws_s3_account_public_access_block", dataSourceAccountPublicAccessBlock)
}

func dataSourceAccountPublicAccessBlock() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceAccountPublicAccessBlockRead,

Expand Down Expand Up @@ -50,27 +51,17 @@ func dataSourceAccountPublicAccessBlockRead(ctx context.Context, d *schema.Resou
accountID = v.(string)
}

input := &s3control.GetPublicAccessBlockInput{
AccountId: aws.String(accountID),
}

log.Printf("[DEBUG] Reading Account access block: %s", input)

output, err := conn.GetPublicAccessBlock(input)
output, err := FindPublicAccessBlockByAccountID(ctx, conn, accountID)

if err != nil {
return diag.Errorf("error reading S3 Account Public Access Block: %s", err)
}

if output == nil || output.PublicAccessBlockConfiguration == nil {
return diag.Errorf("error reading S3 Account Public Access Block (%s): missing public access block configuration", accountID)
return diag.Errorf("reading S3 Account Public Access Block (%s): %s", accountID, err)
}

d.SetId(accountID)
d.Set("block_public_acls", output.PublicAccessBlockConfiguration.BlockPublicAcls)
d.Set("block_public_policy", output.PublicAccessBlockConfiguration.BlockPublicPolicy)
d.Set("ignore_public_acls", output.PublicAccessBlockConfiguration.IgnorePublicAcls)
d.Set("restrict_public_buckets", output.PublicAccessBlockConfiguration.RestrictPublicBuckets)
d.Set("block_public_acls", output.BlockPublicAcls)
d.Set("block_public_policy", output.BlockPublicPolicy)
d.Set("ignore_public_acls", output.IgnorePublicAcls)
d.Set("restrict_public_buckets", output.RestrictPublicBuckets)

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
)

func TestAccS3ControlAccountPublicAccessBlockDataSource_basic(t *testing.T) {
func testAccAccountPublicAccessBlockDataSource_basic(t *testing.T) {
resourceName := "aws_s3_account_public_access_block.test"
dataSourceName := "data.aws_s3_account_public_access_block.test"
resource.ParallelTest(t, resource.TestCase{

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, s3control.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Expand Down
Loading

0 comments on commit 6f101c4

Please sign in to comment.