Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tech debt: Migrate accessanalyzer resources to AWS SDK for Go v2 #31156

Merged
merged 9 commits into from
May 4, 2023
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/aws/aws-sdk-go v1.44.255
github.com/aws/aws-sdk-go-v2 v1.18.0
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.19.11
github.com/aws/aws-sdk-go-v2/service/account v1.10.5
github.com/aws/aws-sdk-go-v2/service/auditmanager v1.24.6
github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.1.3
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7im
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29 h1:J4xhFd6zHhdF9jPP0FQJ6WknzBboGMBNjKOv4iTuw4A=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29/go.mod h1:TwuqRBGzxjQJIwH16/fOZodwXt2Zxa9/cwJC5ke4j7s=
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.19.11 h1:xKLlNhEQlfGpYdm5Ko7Mmylfk3vq4MN20TNGARj66ZM=
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.19.11/go.mod h1:05NIzmwCjR1k1Hhx3RPSkKFRdO9AyHuEJCEgTZG8Ta4=
github.com/aws/aws-sdk-go-v2/service/account v1.10.5 h1:K+Od2Oz2nhQJx3e3Q+ziU11avIlINB0ngfsdc7O2X3M=
github.com/aws/aws-sdk-go-v2/service/account v1.10.5/go.mod h1:sxLUXrqYXCfOBPBBk0azv+UOoFsnrQ9G1ZcICrb9O+0=
github.com/aws/aws-sdk-go-v2/service/auditmanager v1.24.6 h1:UNaqp6XOs26fmBNASN9SF23H3DytHaaRQ/hF/BJNnes=
Expand Down
8 changes: 4 additions & 4 deletions internal/conns/awsclient_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions internal/conns/config_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions internal/service/accessanalyzer/accessanalyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"testing"

"github.com/aws/aws-sdk-go/service/accessanalyzer"
"github.com/aws/aws-sdk-go-v2/service/accessanalyzer"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
)
Expand All @@ -31,11 +31,11 @@ func TestAccAccessAnalyzer_serial(t *testing.T) {
}

func testAccPreCheck(ctx context.Context, t *testing.T) {
conn := acctest.Provider.Meta().(*conns.AWSClient).AccessAnalyzerConn()
conn := acctest.Provider.Meta().(*conns.AWSClient).AccessAnalyzerClient()

input := &accessanalyzer.ListAnalyzersInput{}

_, err := conn.ListAnalyzersWithContext(ctx, input)
_, err := conn.ListAnalyzers(ctx, input)

if acctest.PreCheckSkipError(err) {
t.Skipf("skipping acceptance testing: %s", err)
Expand Down
121 changes: 66 additions & 55 deletions internal/service/accessanalyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import (
"regexp"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/accessanalyzer"
"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/accessanalyzer"
"github.com/aws/aws-sdk-go-v2/service/accessanalyzer/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"
"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"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
Expand All @@ -32,12 +34,13 @@ const (

// @SDKResource("aws_accessanalyzer_analyzer", name="Analyzer")
// @Tags(identifierAttribute="arn")
func ResourceAnalyzer() *schema.Resource {
func resourceAnalyzer() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceAnalyzerCreate,
ReadWithoutTimeout: resourceAnalyzerRead,
UpdateWithoutTimeout: resourceAnalyzerUpdate,
DeleteWithoutTimeout: resourceAnalyzerDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Expand All @@ -59,14 +62,11 @@ func ResourceAnalyzer() *schema.Resource {
names.AttrTags: tftags.TagsSchema(),
names.AttrTagsAll: tftags.TagsSchemaComputed(),
"type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: accessanalyzer.TypeAccount,
ValidateFunc: validation.StringInSlice([]string{
accessanalyzer.TypeAccount,
accessanalyzer.TypeOrganization,
}, false),
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: types.TypeAccount,
ValidateDiagFunc: enum.Validate[types.Type](),
},
},

Expand All @@ -76,37 +76,32 @@ func ResourceAnalyzer() *schema.Resource {

func resourceAnalyzerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).AccessAnalyzerConn()
conn := meta.(*conns.AWSClient).AccessAnalyzerClient()

analyzerName := d.Get("analyzer_name").(string)
input := &accessanalyzer.CreateAnalyzerInput{
AnalyzerName: aws.String(analyzerName),
ClientToken: aws.String(id.UniqueId()),
Tags: GetTagsIn(ctx),
Type: aws.String(d.Get("type").(string)),
Type: types.Type(d.Get("type").(string)),
}

// Handle Organizations eventual consistency
err := retry.RetryContext(ctx, organizationCreationTimeout, func() *retry.RetryError {
_, err := conn.CreateAnalyzerWithContext(ctx, input)

if tfawserr.ErrMessageContains(err, accessanalyzer.ErrCodeValidationException, "You must create an organization") {
return retry.RetryableError(err)
}

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

return nil
})
// Handle Organizations eventual consistency.
_, err := tfresource.RetryWhen(ctx, organizationCreationTimeout,
func() (interface{}, error) {
return conn.CreateAnalyzer(ctx, input)
},
func(err error) (bool, error) {
if errs.IsAErrorMessageContains[*types.ValidationException](err, "You must create an organization") {
return true, err
}

if tfresource.TimedOut(err) {
_, err = conn.CreateAnalyzerWithContext(ctx, input)
}
return false, err
},
)

if err != nil {
return sdkdiag.AppendErrorf(diags, "creating Access Analyzer Analyzer (%s): %s", analyzerName, err)
return sdkdiag.AppendErrorf(diags, "creating IAM Access Analyzer Analyzer (%s): %s", analyzerName, err)
}

d.SetId(analyzerName)
Expand All @@ -116,34 +111,25 @@ func resourceAnalyzerCreate(ctx context.Context, d *schema.ResourceData, meta in

func resourceAnalyzerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).AccessAnalyzerConn()
conn := meta.(*conns.AWSClient).AccessAnalyzerClient()

input := &accessanalyzer.GetAnalyzerInput{
AnalyzerName: aws.String(d.Id()),
}

output, err := conn.GetAnalyzerWithContext(ctx, input)
analyzer, err := findAnalyzerByName(ctx, conn, d.Id())

if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, accessanalyzer.ErrCodeResourceNotFoundException) {
log.Printf("[WARN] Access Analyzer Analyzer (%s) not found, removing from state", d.Id())
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] IAM Access Analyzer Analyzer (%s) not found, removing from state", d.Id())
d.SetId("")
return diags
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "getting Access Analyzer Analyzer (%s): %s", d.Id(), err)
return sdkdiag.AppendErrorf(diags, "reading IAM Access Analyzer Analyzer (%s): %s", d.Id(), err)
}

if output == nil || output.Analyzer == nil {
return sdkdiag.AppendErrorf(diags, "getting Access Analyzer Analyzer (%s): empty response", d.Id())
}
d.Set("analyzer_name", analyzer.Name)
d.Set("arn", analyzer.Arn)
d.Set("type", analyzer.Type)

d.Set("analyzer_name", output.Analyzer.Name)
d.Set("arn", output.Analyzer.Arn)

SetTagsOut(ctx, output.Analyzer.Tags)

d.Set("type", output.Analyzer.Type)
SetTagsOut(ctx, analyzer.Tags)

return diags
}
Expand All @@ -158,21 +144,46 @@ func resourceAnalyzerUpdate(ctx context.Context, d *schema.ResourceData, meta in

func resourceAnalyzerDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).AccessAnalyzerConn()
conn := meta.(*conns.AWSClient).AccessAnalyzerClient()

log.Printf("[DEBUG] Deleting Access Analyzer Analyzer: (%s)", d.Id())
_, err := conn.DeleteAnalyzerWithContext(ctx, &accessanalyzer.DeleteAnalyzerInput{
log.Printf("[DEBUG] Deleting IAM Access Analyzer Analyzer: %s", d.Id())
_, err := conn.DeleteAnalyzer(ctx, &accessanalyzer.DeleteAnalyzerInput{
AnalyzerName: aws.String(d.Id()),
ClientToken: aws.String(id.UniqueId()),
})

if tfawserr.ErrCodeEquals(err, accessanalyzer.ErrCodeResourceNotFoundException) {
if errs.IsA[*types.ResourceNotFoundException](err) {
return diags
}

if err != nil {
return sdkdiag.AppendErrorf(diags, "deleting Access Analyzer Analyzer (%s): %s", d.Id(), err)
return sdkdiag.AppendErrorf(diags, "deleting IAM Access Analyzer Analyzer (%s): %s", d.Id(), err)
}

return diags
}

func findAnalyzerByName(ctx context.Context, conn *accessanalyzer.Client, name string) (*types.AnalyzerSummary, error) {
input := &accessanalyzer.GetAnalyzerInput{
AnalyzerName: aws.String(name),
}

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

if errs.IsA[*types.ResourceNotFoundException](err) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

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

return output.Analyzer, nil
}
Loading