Skip to content

Commit

Permalink
Merge pull request #36939 from mattburgess/cloudformation-awssdkv2-mi…
Browse files Browse the repository at this point in the history
…gration

cloudformation: Migrate to AWS SDK v2
  • Loading branch information
ewbankkit authored May 7, 2024
2 parents 3b24b38 + c75fae6 commit e872a52
Show file tree
Hide file tree
Showing 61 changed files with 1,305 additions and 1,401 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/provider.yml
Original file line number Diff line number Diff line change
Expand Up @@ -306,4 +306,4 @@ jobs:
- uses: avto-dev/markdown-lint@04d43ee9191307b50935a753da3b775ab695eceb # v1.5.0
with:
args: "."
ignore: "./docs ./website/docs ./CHANGELOG.md ./internal/service/cloudformation/testdata/examplecompany-exampleservice-exampleresource/docs"
ignore: "./docs ./website/docs ./CHANGELOG.md ./internal/service/cloudformation/test-fixtures/examplecompany-exampleservice-exampleresource/docs"
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.12.0
github.com/aws/aws-sdk-go-v2/service/cloud9 v1.24.4
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.18.4
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.50.0
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.36.0
github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.4.4
github.com/aws/aws-sdk-go-v2/service/cloudhsmv2 v1.21.4
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ github.com/aws/aws-sdk-go-v2/service/cloud9 v1.24.4 h1:ZqQ1GSSJJMBKPUm/uWfyI7k4W
github.com/aws/aws-sdk-go-v2/service/cloud9 v1.24.4/go.mod h1:qMnYUwVccfXRYqFzpuQ5eoFw2bATWMMdBZaQpGMp2lE=
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.18.4 h1:y9xLchBUDKriRuDsA6OwwzgP9binHw67dR0uicHmOQQ=
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.18.4/go.mod h1:oOvzqGwjzl5fyWi0C7YfOalzMDS8R4yapREwUVV5gBY=
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.50.0 h1:Ap5tOJfeAH1hO2UQc3X3uMlwP7uryFeZXMvZCXIlLSE=
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.50.0/go.mod h1:/v2KYdCW4BaHKayenaWEXOOdxItIwEA3oU0XzuQY3F0=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.36.0 h1:KbT1H0KXc26/M6km03gBWz5v1M5aOq4Cwo+aXJ2BpfM=
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.36.0/go.mod h1:Pphkts8iBnexoEpcMti5fUvN3/yoGRLtl2heOeppF70=
github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.4.4 h1:rIY+RQUvQ4DP5a+vkenhQzGWfQT3LnpAL2b1N0j70F8=
Expand Down
6 changes: 3 additions & 3 deletions internal/conns/awsclient_gen.go

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

2 changes: 1 addition & 1 deletion internal/service/cloudcontrol/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func resourceResourceDelete(ctx context.Context, d *schema.ResourceData, meta in
}

func resourceResourceCustomizeDiffGetSchema(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error {
conn := meta.(*conns.AWSClient).CloudFormationConn(ctx)
conn := meta.(*conns.AWSClient).CloudFormationClient(ctx)

resourceSchema := diff.Get("schema").(string)

Expand Down
20 changes: 10 additions & 10 deletions internal/service/cloudformation/arn.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,38 @@ import (
"fmt"
"strings"

"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go-v2/aws/arn"
)

const (
ARNSeparator = "/"
ARNService = "cloudformation"
arnSeparator = "/"
arnService = "cloudformation"

ResourcePrefixType = "type"
arnResourcePrefixType = "type"
)

// TypeVersionARNToTypeARNAndVersionID converts Type Version Amazon Resource Name (ARN) to Type ARN and Version ID.
// typeVersionARNToTypeARNAndVersionID converts Type Version Amazon Resource Name (ARN) to Type ARN and Version ID.
//
// Given input: arn:aws:cloudformation:us-west-2:123456789012:type/resource/HashiCorp-TerraformAwsProvider-TfAccTestzwv6r2i7/00000001,
// returns arn:aws:cloudformation:us-west-2:123456789012:type/resource/HashiCorp-TerraformAwsProvider-TfAccTestzwv6r2i7 and 00000001.
func TypeVersionARNToTypeARNAndVersionID(inputARN string) (string, string, error) {
func typeVersionARNToTypeARNAndVersionID(inputARN string) (string, string, error) {
parsedARN, err := arn.Parse(inputARN)

if err != nil {
return "", "", fmt.Errorf("parsing ARN (%s): %w", inputARN, err)
}

if actual, expected := parsedARN.Service, ARNService; actual != expected {
if actual, expected := parsedARN.Service, arnService; actual != expected {
return "", "", fmt.Errorf("expected service %s in ARN (%s), got: %s", expected, inputARN, actual)
}

resourceParts := strings.Split(parsedARN.Resource, ARNSeparator)
resourceParts := strings.Split(parsedARN.Resource, arnSeparator)

if actual, expected := len(resourceParts), 4; actual != expected {
return "", "", fmt.Errorf("expected %d resource parts in ARN (%s), got: %d", expected, inputARN, actual)
}

if actual, expected := resourceParts[0], ResourcePrefixType; actual != expected {
if actual, expected := resourceParts[0], arnResourcePrefixType; actual != expected {
return "", "", fmt.Errorf("expected resource prefix %s in ARN (%s), got: %s", expected, inputARN, actual)
}

Expand All @@ -47,7 +47,7 @@ func TypeVersionARNToTypeARNAndVersionID(inputARN string) (string, string, error
Service: parsedARN.Service,
Region: parsedARN.Region,
AccountID: parsedARN.AccountID,
Resource: strings.Join(resourceParts[:3], ARNSeparator),
Resource: strings.Join(resourceParts[:3], arnSeparator),
}.String()

return outputTypeARN, resourceParts[len(resourceParts)-1], nil
Expand Down
5 changes: 2 additions & 3 deletions internal/service/cloudformation/arn_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cloudformation_test
package cloudformation

import (
"regexp"
"testing"

"github.com/YakDriver/regexache"
tfcloudformation "github.com/hashicorp/terraform-provider-aws/internal/service/cloudformation"
)

func TestTypeVersionARNToTypeARNAndVersionID(t *testing.T) {
Expand Down Expand Up @@ -59,7 +58,7 @@ func TestTypeVersionARNToTypeARNAndVersionID(t *testing.T) {
t.Run(testCase.TestName, func(t *testing.T) {
t.Parallel()

gotTypeARN, gotVersionID, err := tfcloudformation.TypeVersionARNToTypeARNAndVersionID(testCase.InputARN)
gotTypeARN, gotVersionID, err := typeVersionARNToTypeARNAndVersionID(testCase.InputARN)

if err == nil && testCase.ExpectedError != nil {
t.Fatalf("expected error %s, got no error", testCase.ExpectedError.String())
Expand Down
84 changes: 84 additions & 0 deletions internal/service/cloudformation/change_set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cloudformation

import (
"context"
"errors"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudformation"
awstypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-provider-aws/internal/enum"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func findChangeSetByTwoPartKey(ctx context.Context, conn *cloudformation.Client, stackID, changeSetName string) (*cloudformation.DescribeChangeSetOutput, error) {
input := &cloudformation.DescribeChangeSetInput{
ChangeSetName: aws.String(changeSetName),
StackName: aws.String(stackID),
}

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

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

if err != nil {
return nil, err
}

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

return output, nil
}

func statusChangeSet(ctx context.Context, conn *cloudformation.Client, stackID, changeSetName string) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := findChangeSetByTwoPartKey(ctx, conn, stackID, changeSetName)

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

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

return output, string(output.Status), nil
}
}

func waitChangeSetCreated(ctx context.Context, conn *cloudformation.Client, stackID, changeSetName string) (*cloudformation.DescribeChangeSetOutput, error) {
const (
timeout = 5 * time.Minute
)
stateConf := retry.StateChangeConf{
Pending: enum.Slice(awstypes.ChangeSetStatusCreateInProgress, awstypes.ChangeSetStatusCreatePending),
Target: enum.Slice(awstypes.ChangeSetStatusCreateComplete),
Timeout: timeout,
Refresh: statusChangeSet(ctx, conn, stackID, changeSetName),
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*cloudformation.DescribeChangeSetOutput); ok {
if output.Status == awstypes.ChangeSetStatusFailed {
tfresource.SetLastError(err, errors.New(aws.ToString(output.StatusReason)))
}

return output, err
}

return nil, err
}
27 changes: 0 additions & 27 deletions internal/service/cloudformation/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,6 @@

package cloudformation

import (
"errors"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudformation"
)

const (
errCodeValidationError = "ValidationError"
)

func stackSetOperationError(apiObjects []*cloudformation.StackSetOperationResultSummary) error {
var errs []error

for _, apiObject := range apiObjects {
if apiObject == nil {
continue
}

errs = append(errs, fmt.Errorf("Account (%s), Region (%s), %s: %s",
aws.StringValue(apiObject.Account),
aws.StringValue(apiObject.Region),
aws.StringValue(apiObject.Status),
aws.StringValue(apiObject.StatusReason),
))
}

return errors.Join(errs...)
}
60 changes: 33 additions & 27 deletions internal/service/cloudformation/export_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,25 @@ import (
"context"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudformation"
"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/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

// @SDKDataSource("aws_cloudformation_export")
func DataSourceExport() *schema.Resource {
// @SDKDataSource("aws_cloudformation_export", name="Export")
func dataSourceExport() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceExportRead,

Schema: map[string]*schema.Schema{
"exporting_stack_id": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Required: true,
Expand All @@ -29,39 +34,40 @@ func DataSourceExport() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"exporting_stack_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceExportRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).CloudFormationConn(ctx)
var value string
conn := meta.(*conns.AWSClient).CloudFormationClient(ctx)

var value *string
name := d.Get("name").(string)
region := meta.(*conns.AWSClient).Region
d.SetId(fmt.Sprintf("cloudformation-exports-%s-%s", region, name))
input := &cloudformation.ListExportsInput{}
err := conn.ListExportsPagesWithContext(ctx, input,
func(page *cloudformation.ListExportsOutput, lastPage bool) bool {
for _, e := range page.Exports {
if name == aws.StringValue(e.Name) {
value = aws.StringValue(e.Value)
d.Set("value", e.Value)
d.Set("exporting_stack_id", e.ExportingStackId)
return false
}

pages := cloudformation.NewListExportsPaginator(conn, input)
for pages.HasMorePages() {
page, err := pages.NextPage(ctx)

if err != nil {
return sdkdiag.AppendErrorf(diags, "listing CloudFormation Exports: %s", err)
}

for _, v := range page.Exports {
if name == aws.ToString(v.Name) {
d.Set("exporting_stack_id", v.ExportingStackId)
value = v.Value
d.Set("value", value)
}
return !lastPage
})
if err != nil {
return sdkdiag.AppendErrorf(diags, "Failed listing CloudFormation exports: %s", err)
}
}
if value == "" {
return sdkdiag.AppendErrorf(diags, "%s was not found in CloudFormation Exports for region %s", name, region)

if value == nil {
return sdkdiag.AppendFromErr(diags, tfresource.NewEmptyResultError(name))
}

d.SetId(fmt.Sprintf("cloudformation-exports-%s-%s", meta.(*conns.AWSClient).Region, name))

return diags
}
14 changes: 14 additions & 0 deletions internal/service/cloudformation/exports.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cloudformation

// Exports for use in other modules.
var (
FindStackByName = findStackByName
FindTypeByName = findTypeByName
WaitChangeSetCreated = waitChangeSetCreated
WaitStackCreated = waitStackCreated
WaitStackDeleted = waitStackDeleted
WaitStackUpdated = waitStackUpdated
)
18 changes: 18 additions & 0 deletions internal/service/cloudformation/exports_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cloudformation

// Exports for use in tests only.
var (
ResourceStack = resourceStack
ResourceStackSet = resourceStackSet
ResourceStackSetInstance = resourceStackSetInstance
ResourceType = resourceType

FindStackInstanceByFourPartKey = findStackInstanceByFourPartKey
FindStackInstanceSummariesByFourPartKey = findStackInstanceSummariesByFourPartKey
FindStackSetByName = findStackSetByName
FindTypeByARN = findTypeByARN
StackSetInstanceResourceIDPartCount = stackSetInstanceResourceIDPartCount
)
Loading

0 comments on commit e872a52

Please sign in to comment.