From c66366796effdf43a8d35e3a2d9249739f4e036f Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Fri, 9 Oct 2020 13:20:39 -0400 Subject: [PATCH 1/4] New Resource: aws_s3control_bucket_policy Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/15412 Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/15416 Output from acceptance testing: ``` Pending ``` --- aws/provider.go | 1 + aws/resource_aws_s3control_bucket_policy.go | 166 ++++++++++++++ ...source_aws_s3control_bucket_policy_test.go | 209 ++++++++++++++++++ .../r/s3control_bucket_policy.html.markdown | 57 +++++ 4 files changed, 433 insertions(+) create mode 100644 aws/resource_aws_s3control_bucket_policy.go create mode 100644 aws/resource_aws_s3control_bucket_policy_test.go create mode 100644 website/docs/r/s3control_bucket_policy.html.markdown diff --git a/aws/provider.go b/aws/provider.go index 693d164daf1..20296dc4f58 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -858,6 +858,7 @@ func Provider() *schema.Provider { "aws_s3_bucket_notification": resourceAwsS3BucketNotification(), "aws_s3_bucket_metric": resourceAwsS3BucketMetric(), "aws_s3_bucket_inventory": resourceAwsS3BucketInventory(), + "aws_s3control_bucket_policy": resourceAwsS3ControlBucketPolicy(), "aws_security_group": resourceAwsSecurityGroup(), "aws_network_interface_sg_attachment": resourceAwsNetworkInterfaceSGAttachment(), "aws_default_security_group": resourceAwsDefaultSecurityGroup(), diff --git a/aws/resource_aws_s3control_bucket_policy.go b/aws/resource_aws_s3control_bucket_policy.go new file mode 100644 index 00000000000..dcbc9369f73 --- /dev/null +++ b/aws/resource_aws_s3control_bucket_policy.go @@ -0,0 +1,166 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/service/s3control" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceAwsS3ControlBucketPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsS3ControlBucketPolicyCreate, + Read: resourceAwsS3ControlBucketPolicyRead, + Update: resourceAwsS3ControlBucketPolicyUpdate, + Delete: resourceAwsS3ControlBucketPolicyDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "bucket": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateArn, + }, + "policy": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsJSON, + DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs, + }, + }, + } +} + +func resourceAwsS3ControlBucketPolicyCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).s3controlconn + + bucket := d.Get("bucket").(string) + + input := &s3control.PutBucketPolicyInput{ + Bucket: aws.String(bucket), + Policy: aws.String(d.Get("policy").(string)), + } + + _, err := conn.PutBucketPolicy(input) + + if err != nil { + return fmt.Errorf("error creating S3 Control Bucket Policy (%s): %w", bucket, err) + } + + d.SetId(bucket) + + return resourceAwsS3ControlBucketPolicyRead(d, meta) +} + +func resourceAwsS3ControlBucketPolicyRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).s3controlconn + + parsedArn, err := arn.Parse(d.Id()) + + if err != nil { + return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", d.Id(), err) + } + + if parsedArn.AccountID == "" { + return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): unknown format", d.Id()) + } + + input := &s3control.GetBucketPolicyInput{ + AccountId: aws.String(parsedArn.AccountID), + Bucket: aws.String(d.Id()), + } + + output, err := conn.GetBucketPolicy(input) + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "NoSuchBucket") { + log.Printf("[WARN] S3 Control Bucket Policy (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "NoSuchBucketPolicy") { + log.Printf("[WARN] S3 Control Bucket Policy (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, "NoSuchOutpost") { + log.Printf("[WARN] S3 Control Bucket Policy (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("error reading S3 Control Bucket Policy (%s): %w", d.Id(), err) + } + + if output == nil { + return fmt.Errorf("error reading S3 Control Bucket Policy (%s): empty response", d.Id()) + } + + d.Set("bucket", d.Id()) + d.Set("policy", output.Policy) + + return nil +} + +func resourceAwsS3ControlBucketPolicyUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).s3controlconn + + input := &s3control.PutBucketPolicyInput{ + Bucket: aws.String(d.Id()), + Policy: aws.String(d.Get("policy").(string)), + } + + _, err := conn.PutBucketPolicy(input) + + if err != nil { + return fmt.Errorf("error updating S3 Control Bucket Policy (%s): %w", d.Id(), err) + } + + return resourceAwsS3ControlBucketPolicyRead(d, meta) +} + +func resourceAwsS3ControlBucketPolicyDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).s3controlconn + + parsedArn, err := arn.Parse(d.Id()) + + if err != nil { + return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", d.Id(), err) + } + + input := &s3control.DeleteBucketPolicyInput{ + AccountId: aws.String(parsedArn.AccountID), + Bucket: aws.String(d.Id()), + } + + _, err = conn.DeleteBucketPolicy(input) + + if tfawserr.ErrCodeEquals(err, "NoSuchBucket") { + return nil + } + + if tfawserr.ErrCodeEquals(err, "NoSuchBucketPolicy") { + return nil + } + + if tfawserr.ErrCodeEquals(err, "NoSuchOutpost") { + return nil + } + + if err != nil { + return fmt.Errorf("error deleting S3 Control Bucket Policy (%s): %w", d.Id(), err) + } + + return nil +} diff --git a/aws/resource_aws_s3control_bucket_policy_test.go b/aws/resource_aws_s3control_bucket_policy_test.go new file mode 100644 index 00000000000..bf7bb59f906 --- /dev/null +++ b/aws/resource_aws_s3control_bucket_policy_test.go @@ -0,0 +1,209 @@ +package aws + +import ( + "fmt" + "regexp" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/service/s3control" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccAWSS3ControlBucketPolicy_basic(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_s3control_bucket_policy.test" + s3ControlBucketResourceName := "aws_s3control_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSS3ControlBucketPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:*"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSS3ControlBucketPolicyExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "arn"), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:\*`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSS3ControlBucketPolicy_disappears(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_s3control_bucket_policy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSS3ControlBucketPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:*"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSS3ControlBucketPolicyExists(resourceName), + testAccCheckResourceDisappears(testAccProvider, resourceAwsS3ControlBucketPolicy(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAWSS3ControlBucketPolicy_Policy(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_s3control_bucket_policy.test" + s3ControlBucketResourceName := "aws_s3control_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSS3ControlBucketPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:CreateBucket"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSS3ControlBucketPolicyExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "bucket"), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:CreateBucket`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:DeleteBucket"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSS3ControlBucketPolicyExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "bucket"), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:DeleteBucket`)), + ), + }, + }, + }) +} + +func testAccCheckAWSS3ControlBucketPolicyDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).s3controlconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_s3control_bucket_policy" { + continue + } + + parsedArn, err := arn.Parse(rs.Primary.ID) + + if err != nil { + return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", rs.Primary.ID, err) + } + + input := &s3control.GetBucketPolicyInput{ + AccountId: aws.String(parsedArn.AccountID), + Bucket: aws.String(rs.Primary.ID), + } + + _, err = conn.GetBucketPolicy(input) + + if tfawserr.ErrCodeEquals(err, "NoSuchBucket") { + return nil + } + + if tfawserr.ErrCodeEquals(err, "NoSuchBucketPolicy") { + return nil + } + + if tfawserr.ErrCodeEquals(err, "NoSuchOutpost") { + return nil + } + + if err != nil { + return err + } + + return fmt.Errorf("S3 Control Bucket Policy (%s) still exists", rs.Primary.ID) + } + + return nil +} + +func testAccCheckAWSS3ControlBucketPolicyExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("no resource ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).s3controlconn + + parsedArn, err := arn.Parse(rs.Primary.ID) + + if err != nil { + return fmt.Errorf("error parsing S3 Control Bucket ARN (%s): %w", rs.Primary.ID, err) + } + + input := &s3control.GetBucketPolicyInput{ + AccountId: aws.String(parsedArn.AccountID), + Bucket: aws.String(rs.Primary.ID), + } + + _, err = conn.GetBucketPolicy(input) + + if err != nil { + return err + } + + return nil + } +} + +func testAccAWSS3ControlBucketPolicyConfig_Policy(rName, action string) string { + return fmt.Sprintf(` +data "aws_outposts_outposts" "test" {} + +data "aws_outposts_outpost" "test" { + id = tolist(data.aws_outposts_outposts.test.ids)[0] +} + +resource "aws_s3control_bucket" "test" { + bucket = %[1]q + outpost_id = data.aws_outposts_outpost.test.id +} + +resource "aws_s3control_bucket_policy" "test" { + bucket = aws_s3control_bucket.test.arn + policy = jsonencode({ + Id = "testBucketPolicy" + Statement = [ + { + Action = %[2]q + Effect = "Allow" + Principal = { + AWS = "*" + } + Resource = aws_s3control_bucket.test.arn + Sid = "st1" + } + ] + Version = "2012-10-17" + }) +} +`, rName, action) +} diff --git a/website/docs/r/s3control_bucket_policy.html.markdown b/website/docs/r/s3control_bucket_policy.html.markdown new file mode 100644 index 00000000000..5124f69a839 --- /dev/null +++ b/website/docs/r/s3control_bucket_policy.html.markdown @@ -0,0 +1,57 @@ +--- +subcategory: "S3 Control" +layout: "aws" +page_title: "AWS: aws_s3control_bucket_policy" +description: |- + Manages an S3 Control Bucket Policy. +--- + +# Resource: aws_s3control_bucket_policy + +Provides a resource to manage an S3 Control Bucket Policy. + +-> This functionality is for managing [S3 on Outposts](https://docs.aws.amazon.com/AmazonS3/latest/dev/S3onOutposts.html). To manage S3 Bucket Policies in an AWS Partition, see the [`aws_s3_bucket_policy` resource](/docs/providers/aws/r/s3_bucket_policy.html). + +## Example Usage + +```hcl +resource "aws_s3control_bucket_policy" "example" { + bucket = aws_s3control_bucket.example.arn + policy = jsonencode({ + Id = "testBucketPolicy" + Statement = [ + { + Action = "s3-outposts:PutBucketLifecycleConfiguration" + Effect = "Deny" + Principal = { + AWS = "*" + } + Resource = aws_s3control_bucket.example.arn + Sid = "statement1" + } + ] + Version = "2012-10-17" + }) +} +``` + +## Argument Reference + +The following arguments are required: + +* `bucket` - (Required) Amazon Resource Name (ARN) of the bucket. +* `policy` - (Required) JSON string of the resource policy. For more information about building AWS IAM policy documents with Terraform, see the [AWS IAM Policy Document Guide](https://learn.hashicorp.com/terraform/aws/iam-policy). + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - Amazon Resource Name (ARN) of the bucket. + +## Import + +S3 Control Bucket Policies can be imported using the Amazon Resource Name (ARN), e.g. + +``` +$ terraform import aws_s3control_bucket_policy.example arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-12345678/bucket/example +``` From 81818e6194f483419b19473ed59ee4fcde1c8837 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Fri, 9 Oct 2020 19:17:49 -0400 Subject: [PATCH 2/4] tests/resource/aws_s3control_bucket_policy: Fixes since Public Access Block is always enabled for S3 Control Buckets Output from acceptance testing: ``` --- PASS: TestAccAWSS3ControlBucketPolicy_disappears (32.85s) --- PASS: TestAccAWSS3ControlBucketPolicy_Policy (43.13s) --- PASS: TestAccAWSS3ControlBucketPolicy_basic (106.91s) ``` --- ...esource_aws_s3control_bucket_policy_test.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/aws/resource_aws_s3control_bucket_policy_test.go b/aws/resource_aws_s3control_bucket_policy_test.go index bf7bb59f906..94bcc3f8335 100644 --- a/aws/resource_aws_s3control_bucket_policy_test.go +++ b/aws/resource_aws_s3control_bucket_policy_test.go @@ -17,7 +17,6 @@ import ( func TestAccAWSS3ControlBucketPolicy_basic(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_s3control_bucket_policy.test" - s3ControlBucketResourceName := "aws_s3control_bucket.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) }, @@ -28,7 +27,7 @@ func TestAccAWSS3ControlBucketPolicy_basic(t *testing.T) { Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:*"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSS3ControlBucketPolicyExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "arn"), + resource.TestCheckResourceAttrPair(resourceName, "bucket", "aws_s3control_bucket.test", "arn"), resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:\*`)), ), }, @@ -65,7 +64,6 @@ func TestAccAWSS3ControlBucketPolicy_disappears(t *testing.T) { func TestAccAWSS3ControlBucketPolicy_Policy(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_s3control_bucket_policy.test" - s3ControlBucketResourceName := "aws_s3control_bucket.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) }, @@ -73,11 +71,10 @@ func TestAccAWSS3ControlBucketPolicy_Policy(t *testing.T) { CheckDestroy: testAccCheckAWSS3ControlBucketPolicyDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:CreateBucket"), + Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:GetObject"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSS3ControlBucketPolicyExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "bucket"), - resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:CreateBucket`)), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:GetObject`)), ), }, { @@ -86,11 +83,10 @@ func TestAccAWSS3ControlBucketPolicy_Policy(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:DeleteBucket"), + Config: testAccAWSS3ControlBucketPolicyConfig_Policy(rName, "s3-outposts:PutObject"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSS3ControlBucketPolicyExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "bucket", s3ControlBucketResourceName, "bucket"), - resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:DeleteBucket`)), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`s3-outposts:PutObject`)), ), }, }, @@ -194,11 +190,11 @@ resource "aws_s3control_bucket_policy" "test" { Statement = [ { Action = %[2]q - Effect = "Allow" + Effect = "Deny" Principal = { AWS = "*" } - Resource = aws_s3control_bucket.test.arn + Resource = "${aws_s3control_bucket.test.arn}/object/test" Sid = "st1" } ] From 69fc2d573f6e6392151edc0cb123ad1906d894af Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Fri, 9 Oct 2020 19:20:36 -0400 Subject: [PATCH 3/4] resource/aws_s3control_bucket_policy: terrafmt fixes --- aws/resource_aws_s3control_bucket_policy_test.go | 2 +- website/docs/r/s3control_bucket_policy.html.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_s3control_bucket_policy_test.go b/aws/resource_aws_s3control_bucket_policy_test.go index 94bcc3f8335..294742ba1cd 100644 --- a/aws/resource_aws_s3control_bucket_policy_test.go +++ b/aws/resource_aws_s3control_bucket_policy_test.go @@ -186,7 +186,7 @@ resource "aws_s3control_bucket" "test" { resource "aws_s3control_bucket_policy" "test" { bucket = aws_s3control_bucket.test.arn policy = jsonencode({ - Id = "testBucketPolicy" + Id = "testBucketPolicy" Statement = [ { Action = %[2]q diff --git a/website/docs/r/s3control_bucket_policy.html.markdown b/website/docs/r/s3control_bucket_policy.html.markdown index 5124f69a839..8fc4ffe5fc3 100644 --- a/website/docs/r/s3control_bucket_policy.html.markdown +++ b/website/docs/r/s3control_bucket_policy.html.markdown @@ -18,7 +18,7 @@ Provides a resource to manage an S3 Control Bucket Policy. resource "aws_s3control_bucket_policy" "example" { bucket = aws_s3control_bucket.example.arn policy = jsonencode({ - Id = "testBucketPolicy" + Id = "testBucketPolicy" Statement = [ { Action = "s3-outposts:PutBucketLifecycleConfiguration" From 1278575bd57d3561f88032bad7d00622c9d307c9 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Tue, 27 Oct 2020 14:50:53 -0400 Subject: [PATCH 4/4] Update aws/resource_aws_s3control_bucket_policy_test.go --- aws/resource_aws_s3control_bucket_policy_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_s3control_bucket_policy_test.go b/aws/resource_aws_s3control_bucket_policy_test.go index 294742ba1cd..7d42f8723a8 100644 --- a/aws/resource_aws_s3control_bucket_policy_test.go +++ b/aws/resource_aws_s3control_bucket_policy_test.go @@ -115,15 +115,15 @@ func testAccCheckAWSS3ControlBucketPolicyDestroy(s *terraform.State) error { _, err = conn.GetBucketPolicy(input) if tfawserr.ErrCodeEquals(err, "NoSuchBucket") { - return nil + continue } if tfawserr.ErrCodeEquals(err, "NoSuchBucketPolicy") { - return nil + continue } if tfawserr.ErrCodeEquals(err, "NoSuchOutpost") { - return nil + continue } if err != nil {