Skip to content

Commit

Permalink
Merge pull request #37510 from hashicorp/td-migrate-route53-to-aws-sd…
Browse files Browse the repository at this point in the history
…k-v2

Migrate `route53` resources to AWS SDK for Go v2
  • Loading branch information
ewbankkit authored May 20, 2024
2 parents 1eb9b2d + bbc60a8 commit 2ad553c
Show file tree
Hide file tree
Showing 64 changed files with 3,068 additions and 3,264 deletions.
15 changes: 15 additions & 0 deletions .changelog/37510.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```release-note:enhancement
resource/aws_route53_health_check: Add plan-time validation of `cloudwatch_alarm_region`
```

```release-note:enhancement
resource/aws_route53_vpc_association_authorization: Add plan-time validation of `vpc_region`
```

```release-note:enhancement
resource/aws_route53_zone_association: Add plan-time validation of `vpc_region`
```

```release-note:enhancement
resource/aws_route53_record: Add plan-time validation of `latency_routing_policy.region`
```
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/resourcegroups v1.22.3
github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.21.7
github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.11.3
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.7
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.7
github.com/aws/aws-sdk-go-v2/service/route53profiles v1.0.4
github.com/aws/aws-sdk-go-v2/service/s3 v1.54.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.21.7 h1:1KTeOEq
github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.21.7/go.mod h1:I3uJLgoT83sDh9YRQdcUDoauftf7ySq9hFB7Z6O7p2c=
github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.11.3 h1:JDEMYGrzwr5QGqrwRFRCeui7LSAmsR/d0ZXdPP3duYA=
github.com/aws/aws-sdk-go-v2/service/rolesanywhere v1.11.3/go.mod h1:SZ63U4KIN2oaEhQYnmCRLRRcR8bMz/HKdPwuRd5Q5nk=
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.7 h1:dP8gy5fBzlwU5f4QFJtFFYfSHeuom1vuC8e2LJaEgS8=
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.7/go.mod h1:CxB0DFnZHDkZZWurSFWDdgkKmjaAFtRIk85hoUy4XhI=
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.7 h1:lu5Mc8UkEdsvWq7hL2yUyV6xSvqYkpVe+s2SqkZYVw8=
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.7/go.mod h1:/KwP4cRCKqB+JT3emX3JDZ4j7MbNIttyqiYWkJE6jNk=
github.com/aws/aws-sdk-go-v2/service/route53profiles v1.0.4 h1:bYqB/UqCqmxXYwoEZQXAwlOWggxznTVgtRgw6LhCT4E=
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.

87 changes: 87 additions & 0 deletions internal/service/route53/change_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package route53

import (
"context"
"math/rand"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/route53"
awstypes "github.com/aws/aws-sdk-go-v2/service/route53/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 findChangeByID(ctx context.Context, conn *route53.Client, id string) (*awstypes.ChangeInfo, error) {
input := &route53.GetChangeInput{
Id: aws.String(id),
}

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

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

if err != nil {
return nil, err
}

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

return output.ChangeInfo, nil
}

func statusChange(ctx context.Context, conn *route53.Client, id string) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := findChangeByID(ctx, conn, id)

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

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

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

func waitChangeInsync(ctx context.Context, conn *route53.Client, id string) (*awstypes.ChangeInfo, error) {
// Route53 is vulnerable to throttling so longer delays, poll intervals helps significantly to avoid.
const (
timeout = 30 * time.Minute
minTimeout = 5 * time.Second
pollInterval = 15 * time.Second
minDelay = 10
maxDelay = 30
)
stateConf := &retry.StateChangeConf{
Pending: enum.Slice(awstypes.ChangeStatusPending),
Target: enum.Slice(awstypes.ChangeStatusInsync),
Refresh: statusChange(ctx, conn, id),
Delay: time.Duration(rand.Int63n(maxDelay-minDelay)+minDelay) * time.Second,
MinTimeout: minTimeout,
PollInterval: pollInterval,
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

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

return nil, err
}
136 changes: 68 additions & 68 deletions internal/service/route53/cidr_collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"time"

"github.com/YakDriver/regexache"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/route53"
awstypes "github.com/aws/aws-sdk-go-v2/service/route53/types"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
Expand All @@ -21,31 +21,34 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag"
"github.com/hashicorp/terraform-provider-aws/internal/framework"
"github.com/hashicorp/terraform-provider-aws/internal/framework/flex"
fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @FrameworkResource
func newResourceCIDRCollection(context.Context) (resource.ResourceWithConfigure, error) {
r := &resourceCIDRCollection{}
func newCIDRCollectionResource(context.Context) (resource.ResourceWithConfigure, error) {
r := &cidrCollectionResource{}

return r, nil
}

type resourceCIDRCollection struct {
type cidrCollectionResource struct {
framework.ResourceWithConfigure
framework.WithNoUpdate
framework.WithImportByID
}

func (r *resourceCIDRCollection) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
func (*cidrCollectionResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
response.TypeName = "aws_route53_cidr_collection"
}

func (r *resourceCIDRCollection) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
func (r *cidrCollectionResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) {
response.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
names.AttrARN: framework.ARNAttributeComputedOnly(),
names.AttrID: framework.IDAttribute(),
Expand All @@ -66,26 +69,27 @@ func (r *resourceCIDRCollection) Schema(ctx context.Context, req resource.Schema
}
}

func (r *resourceCIDRCollection) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
var data resourceCIDRCollectionData

func (r *cidrCollectionResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
var data cidrCollectionResourceModel
response.Diagnostics.Append(request.Plan.Get(ctx, &data)...)

if response.Diagnostics.HasError() {
return
}

conn := r.Meta().Route53Conn(ctx)
conn := r.Meta().Route53Client(ctx)

name := data.Name.ValueString()
input := &route53.CreateCidrCollectionInput{
CallerReference: aws.String(id.UniqueId()),
Name: aws.String(name),
}

outputRaw, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, 2*time.Minute, func() (interface{}, error) {
return conn.CreateCidrCollectionWithContext(ctx, input)
}, route53.ErrCodeConcurrentModification)
const (
timeout = 2 * time.Minute
)
outputRaw, err := tfresource.RetryWhenIsA[*awstypes.ConcurrentModification](ctx, timeout, func() (interface{}, error) {
return conn.CreateCidrCollection(ctx, input)
})

if err != nil {
response.Diagnostics.AddError(fmt.Sprintf("creating Route 53 CIDR Collection (%s)", name), err.Error())
Expand All @@ -94,23 +98,21 @@ func (r *resourceCIDRCollection) Create(ctx context.Context, request resource.Cr
}

output := outputRaw.(*route53.CreateCidrCollectionOutput)
data.ARN = flex.StringToFramework(ctx, output.Collection.Arn)
data.ID = flex.StringToFramework(ctx, output.Collection.Id)
data.Version = flex.Int64ToFramework(ctx, output.Collection.Version)
data.ARN = fwflex.StringToFramework(ctx, output.Collection.Arn)
data.ID = fwflex.StringToFramework(ctx, output.Collection.Id)
data.Version = fwflex.Int64ToFramework(ctx, output.Collection.Version)

response.Diagnostics.Append(response.State.Set(ctx, &data)...)
}

func (r *resourceCIDRCollection) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
var data resourceCIDRCollectionData

func (r *cidrCollectionResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
var data cidrCollectionResourceModel
response.Diagnostics.Append(request.State.Get(ctx, &data)...)

if response.Diagnostics.HasError() {
return
}

conn := r.Meta().Route53Conn(ctx)
conn := r.Meta().Route53Client(ctx)

output, err := findCIDRCollectionByID(ctx, conn, data.ID.ValueString())

Expand All @@ -127,84 +129,82 @@ func (r *resourceCIDRCollection) Read(ctx context.Context, request resource.Read
return
}

data.ARN = flex.StringToFramework(ctx, output.Arn)
data.Name = flex.StringToFramework(ctx, output.Name)
data.Version = flex.Int64ToFramework(ctx, output.Version)
data.ARN = fwflex.StringToFramework(ctx, output.Arn)
data.Name = fwflex.StringToFramework(ctx, output.Name)
data.Version = fwflex.Int64ToFramework(ctx, output.Version)

response.Diagnostics.Append(response.State.Set(ctx, &data)...)
}

func (r *resourceCIDRCollection) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
// Noop.
}

func (r *resourceCIDRCollection) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
var data resourceCIDRCollectionData

func (r *cidrCollectionResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
var data cidrCollectionResourceModel
response.Diagnostics.Append(request.State.Get(ctx, &data)...)

if response.Diagnostics.HasError() {
return
}

conn := r.Meta().Route53Conn(ctx)
conn := r.Meta().Route53Client(ctx)

tflog.Debug(ctx, "deleting Route 53 CIDR Collection", map[string]interface{}{
names.AttrID: data.ID.ValueString(),
})

_, err := conn.DeleteCidrCollectionWithContext(ctx, &route53.DeleteCidrCollectionInput{
Id: flex.StringFromFramework(ctx, data.ID),
_, err := conn.DeleteCidrCollection(ctx, &route53.DeleteCidrCollectionInput{
Id: fwflex.StringFromFramework(ctx, data.ID),
})

if errs.IsA[*awstypes.NoSuchCidrCollectionException](err) {
return
}

if err != nil {
response.Diagnostics.AddError(fmt.Sprintf("deleting Route 53 CIDR Collection (%s)", data.ID.ValueString()), err.Error())

return
}
}

func (r *resourceCIDRCollection) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root(names.AttrID), request, response)
}

type resourceCIDRCollectionData struct {
type cidrCollectionResourceModel struct {
ARN types.String `tfsdk:"arn"`
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Version types.Int64 `tfsdk:"version"`
}

func findCIDRCollectionByID(ctx context.Context, conn *route53.Route53, id string) (*route53.CollectionSummary, error) {
func findCIDRCollectionByID(ctx context.Context, conn *route53.Client, id string) (*awstypes.CollectionSummary, error) {
input := &route53.ListCidrCollectionsInput{}
var output *route53.CollectionSummary

err := conn.ListCidrCollectionsPagesWithContext(ctx, input, func(page *route53.ListCidrCollectionsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, v := range page.CidrCollections {
if v == nil {
continue
}

if aws.StringValue(v.Id) == id {
output = v

return false
}
}

return !lastPage
return findCIDRCollection(ctx, conn, input, func(v *awstypes.CollectionSummary) bool {
return aws.ToString(v.Id) == id
})
}

func findCIDRCollection(ctx context.Context, conn *route53.Client, input *route53.ListCidrCollectionsInput, filter tfslices.Predicate[*awstypes.CollectionSummary]) (*awstypes.CollectionSummary, error) {
output, err := findCIDRCollections(ctx, conn, input, filter)

if err != nil {
return nil, err
}

if output == nil {
return nil, &retry.NotFoundError{}
return tfresource.AssertSingleValueResult(output)
}

func findCIDRCollections(ctx context.Context, conn *route53.Client, input *route53.ListCidrCollectionsInput, filter tfslices.Predicate[*awstypes.CollectionSummary]) ([]awstypes.CollectionSummary, error) {
var output []awstypes.CollectionSummary

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

if err != nil {
return nil, err
}

for _, v := range page.CidrCollections {
if filter(&v) {
output = append(output, v)
}
}
}

return output, nil
Expand Down
Loading

0 comments on commit 2ad553c

Please sign in to comment.