Skip to content

Commit

Permalink
resource/aws_accessanalyzer_analyzer: Support ORGANIZATION value in t…
Browse files Browse the repository at this point in the history
…ype argument (#14493)

Reference: #12593

Output from acceptance testing in Organizations testing account:

```
--- PASS: TestAccAWSAccessAnalyzer_serial (344.90s)
    --- PASS: TestAccAWSAccessAnalyzer_serial/Analyzer (344.90s)
        --- PASS: TestAccAWSAccessAnalyzer_serial/Analyzer/basic (10.64s)
        --- PASS: TestAccAWSAccessAnalyzer_serial/Analyzer/disappears (7.41s)
        --- PASS: TestAccAWSAccessAnalyzer_serial/Analyzer/Tags (22.00s)
        --- PASS: TestAccAWSAccessAnalyzer_serial/Analyzer/Type_Organization (304.86s)
```
  • Loading branch information
bflad authored Aug 12, 2020
1 parent 67b0438 commit d90279c
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 5 deletions.
30 changes: 29 additions & 1 deletion aws/resource_aws_accessanalyzer_analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/accessanalyzer"
Expand All @@ -12,6 +13,14 @@ import (
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

const (
// Maximum amount of time to wait for Organizations eventual consistency on creation
// This timeout value is much higher than usual since the cross-service validation
// appears to be consistently caching for 5 minutes:
// --- PASS: TestAccAWSAccessAnalyzer_serial/Analyzer/Type_Organization (315.86s)
accessAnalyzerOrganizationCreationTimeout = 10 * time.Minute
)

func resourceAwsAccessAnalyzerAnalyzer() *schema.Resource {
return &schema.Resource{
Create: resourceAwsAccessAnalyzerAnalyzerCreate,
Expand All @@ -37,9 +46,11 @@ func resourceAwsAccessAnalyzerAnalyzer() *schema.Resource {
"type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: accessanalyzer.TypeAccount,
ValidateFunc: validation.StringInSlice([]string{
accessanalyzer.TypeAccount,
accessanalyzer.TypeOrganization,
}, false),
},
},
Expand All @@ -57,7 +68,24 @@ func resourceAwsAccessAnalyzerAnalyzerCreate(d *schema.ResourceData, meta interf
Type: aws.String(d.Get("type").(string)),
}

_, err := conn.CreateAnalyzer(input)
// Handle Organizations eventual consistency
err := resource.Retry(accessAnalyzerOrganizationCreationTimeout, func() *resource.RetryError {
_, err := conn.CreateAnalyzer(input)

if isAWSErr(err, accessanalyzer.ErrCodeValidationException, "You must create an organization") {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})

if isResourceTimeoutError(err) {
_, err = conn.CreateAnalyzer(input)
}

if err != nil {
return fmt.Errorf("error creating Access Analyzer Analyzer (%s): %s", analyzerName, err)
Expand Down
49 changes: 49 additions & 0 deletions aws/resource_aws_accessanalyzer_analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,38 @@ func testAccAWSAccessAnalyzerAnalyzer_Tags(t *testing.T) {
})
}

// This test can be run via the pattern: TestAccAWSAccessAnalyzer
func testAccAWSAccessAnalyzerAnalyzer_Type_Organization(t *testing.T) {
var analyzer accessanalyzer.AnalyzerSummary

rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_accessanalyzer_analyzer.test"

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAWSAccessAnalyzer(t)
testAccOrganizationsAccountPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckAccessAnalyzerAnalyzerDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAccessAnalyzerAnalyzerConfigTypeOrganization(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsAccessAnalyzerAnalyzerExists(resourceName, &analyzer),
resource.TestCheckResourceAttr(resourceName, "type", accessanalyzer.TypeOrganization),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckAccessAnalyzerAnalyzerDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).accessanalyzerconn

Expand Down Expand Up @@ -218,3 +250,20 @@ resource "aws_accessanalyzer_analyzer" "test" {
}
`, rName, tagKey1, tagValue1, tagKey2, tagValue2)
}

func testAccAWSAccessAnalyzerAnalyzerConfigTypeOrganization(rName string) string {
return fmt.Sprintf(`
data "aws_partition" "current" {}
resource "aws_organizations_organization" "test" {
aws_service_access_principals = ["access-analyzer.${data.aws_partition.current.dns_suffix}"]
}
resource "aws_accessanalyzer_analyzer" "test" {
depends_on = [aws_organizations_organization.test]
analyzer_name = %[1]q
type = "ORGANIZATION"
}
`, rName)
}
7 changes: 4 additions & 3 deletions aws/resource_aws_accessanalyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import (
func TestAccAWSAccessAnalyzer_serial(t *testing.T) {
testCases := map[string]map[string]func(t *testing.T){
"Analyzer": {
"basic": testAccAWSAccessAnalyzerAnalyzer_basic,
"disappears": testAccAWSAccessAnalyzerAnalyzer_disappears,
"Tags": testAccAWSAccessAnalyzerAnalyzer_Tags,
"basic": testAccAWSAccessAnalyzerAnalyzer_basic,
"disappears": testAccAWSAccessAnalyzerAnalyzer_disappears,
"Tags": testAccAWSAccessAnalyzerAnalyzer_Tags,
"Type_Organization": testAccAWSAccessAnalyzerAnalyzer_Type_Organization,
},
}

Expand Down
19 changes: 18 additions & 1 deletion website/docs/r/accessanalyzer_analyzer.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,29 @@ Manages an Access Analyzer Analyzer. More information can be found in the [Acces

## Example Usage

### Account Analyzer

```hcl
resource "aws_accessanalyzer_analyzer" "example" {
analyzer_name = "example"
}
```

### Organization Analyzer

```hcl
resource "aws_organizations_organization" "example" {
aws_service_access_principals = ["access-analyzer.amazonaws.com"]
}
resource "aws_accessanalyzer_analyzer" "example" {
depends_on = [aws_organizations_organization.example]
analyzer_name = "example"
type = "ORGANIZATION"
}
```

## Argument Reference

The following arguments are required:
Expand All @@ -27,7 +44,7 @@ The following arguments are required:
The following arguments are optional:

* `tags` - (Optional) Key-value map of resource tags.
* `type` - (Optional) Type of Analyzer. Valid value is currently only `ACCOUNT`. Defaults to `ACCOUNT`.
* `type` - (Optional) Type of Analyzer. Valid values are `ACCOUNT` or `ORGANIZATION`. Defaults to `ACCOUNT`.

## Attributes Reference

Expand Down

0 comments on commit d90279c

Please sign in to comment.