From b10ba5e2a38db49c24abc0aafcc543c1b4d87403 Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Mon, 26 Feb 2024 11:46:09 -0500 Subject: [PATCH 01/35] cross account attachment resource --- .../cross_account_attachment.go | 534 ++++++++++++++++++ .../cross_account_attachment_test.go | 476 ++++++++++++++++ .../service/globalaccelerator/exports_test.go | 13 + .../globalaccelerator/service_package_gen.go | 7 +- ...tor_cross_account_attachment.html.markdown | 80 +++ 5 files changed, 1109 insertions(+), 1 deletion(-) create mode 100644 internal/service/globalaccelerator/cross_account_attachment.go create mode 100644 internal/service/globalaccelerator/cross_account_attachment_test.go create mode 100644 internal/service/globalaccelerator/exports_test.go create mode 100644 website/docs/r/globalaccelerator_cross_account_attachment.html.markdown diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go new file mode 100644 index 00000000000..6f25ac678bf --- /dev/null +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -0,0 +1,534 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package globalaccelerator + +import ( + "context" + "errors" + "fmt" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/globalaccelerator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="Cross Account Attachment") +func newResourceCrossAccountAttachment(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceCrossAccountAttachment{} + + r.SetDefaultCreateTimeout(30 * time.Minute) + r.SetDefaultUpdateTimeout(30 * time.Minute) + r.SetDefaultDeleteTimeout(30 * time.Minute) + + return r, nil +} + +const ( + ResNameCrossAccountAttachment = "Cross Account Attachment" +) + +type resourceCrossAccountAttachment struct { + framework.ResourceWithConfigure + framework.WithTimeouts +} + +func (r *resourceCrossAccountAttachment) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_globalaccelerator_cross_account_attachment" +} + +func (r *resourceCrossAccountAttachment) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "attachment_arn": framework.ARNAttributeComputedOnly(), + "id": framework.IDAttribute(), + "name": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "principals": schema.ListAttribute{ + Optional: true, + ElementType: types.StringType, + PlanModifiers: []planmodifier.List{ + listplanmodifier.RequiresReplace(), + }, + }, + "resources": schema.ListAttribute{ + Optional: true, + ElementType: ResourceDataElementType, + PlanModifiers: []planmodifier.List{ + listplanmodifier.RequiresReplace(), + }, + }, + "created_time": schema.StringAttribute{ + Computed: true, + }, + "last_modified_time": schema.StringAttribute{ + Computed: true, + }, + }, + } +} + +func (r *resourceCrossAccountAttachment) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().GlobalAcceleratorConn(ctx) + + var plan resourceCrossAccountAttachmentData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + input := &globalaccelerator.CreateCrossAccountAttachmentInput{ + IdempotencyToken: aws.String(id.UniqueId()), + Name: aws.String(plan.Name.ValueString()), + Tags: getTagsIn(ctx), + } + + if !plan.Principals.IsNull() { + input.Principals = flex.ExpandFrameworkStringList(ctx, plan.Principals) + } + + if !plan.Resources.IsNull() { + var tfResources []ResourceData + diags := plan.Resources.ElementsAs(ctx, &tfResources, false) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + input.Resources = expandResources(tfResources) + } + + out, err := conn.CreateCrossAccountAttachmentWithContext(ctx, input) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GlobalAccelerator, create.ErrActionCreating, ResNameCrossAccountAttachment, plan.Name.String(), err), + err.Error(), + ) + return + } + if out == nil || out.CrossAccountAttachment == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GlobalAccelerator, create.ErrActionCreating, ResNameCrossAccountAttachment, plan.Name.String(), nil), + errors.New("empty output").Error(), + ) + return + } + + plan.ID = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) + state := plan + state.ARN = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) + + state.CreatedTime = types.StringValue(out.CrossAccountAttachment.CreatedTime.Format(time.RFC3339)) + if out.CrossAccountAttachment.LastModifiedTime != nil { + state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) + } + + resp.Diagnostics.Append(resp.State.Set(ctx, state)...) +} + +func (r *resourceCrossAccountAttachment) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().GlobalAcceleratorConn(ctx) + + var state resourceCrossAccountAttachmentData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + input := &globalaccelerator.DescribeCrossAccountAttachmentInput{ + AttachmentArn: aws.String(state.ARN.ValueString()), + } + out, err := conn.DescribeCrossAccountAttachment(input) + + var nfe *globalaccelerator.AttachmentNotFoundException + if errors.As(err, &nfe) { + resp.State.RemoveResource(ctx) + return + } + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.GlobalAccelerator, create.ErrActionSetting, ResNameCrossAccountAttachment, state.ID.String(), err), + err.Error(), + ) + return + } + + state.ARN = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) + state.Name = flex.StringToFramework(ctx, out.CrossAccountAttachment.Name) + state.CreatedTime = types.StringValue(out.CrossAccountAttachment.CreatedTime.Format(time.RFC3339)) + if out.CrossAccountAttachment.LastModifiedTime != nil { + state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) + } + + resources, errDiags := flattenResources(ctx, out.CrossAccountAttachment.Resources) + resp.Diagnostics.Append(errDiags...) + if resp.Diagnostics.HasError() { + return + } + state.Resources = resources + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceCrossAccountAttachment) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().GlobalAcceleratorConn(ctx) + + var plan, state resourceCrossAccountAttachmentData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + input := &globalaccelerator.UpdateCrossAccountAttachmentInput{ + AttachmentArn: aws.String(state.ARN.ValueString()), + } + + var diags diag.Diagnostics + if !plan.Principals.Equal(state.Principals) { + input.AddPrincipals, input.RemovePrincipals, diags = DiffPrincipals(ctx, state.Principals, plan.Principals) + resp.Diagnostics.Append(diags...) + } + + if !plan.Resources.Equal(state.Resources) { + input.AddResources, input.RemoveResources, diags = DiffResources(ctx, state.Resources, plan.Resources) + resp.Diagnostics.Append(diags...) + } + + if !plan.Name.Equal(state.Name) { + input.Name = aws.String(plan.Name.ValueString()) + } + + if input.Name != nil || input.AddPrincipals != nil || input.RemovePrincipals != nil || input.AddResources != nil || input.RemoveResources != nil { + out, err := conn.UpdateCrossAccountAttachmentWithContext(ctx, input) + if err != nil { + resp.Diagnostics.AddError( + "Error updating CrossAccountAttachment", + fmt.Sprintf("Could not update CrossAccountAttachment %s: %s", state.ARN.ValueString(), err), + ) + return + } + + state.CreatedTime = types.StringValue(out.CrossAccountAttachment.CreatedTime.Format(time.RFC3339)) + if out.CrossAccountAttachment.LastModifiedTime != nil { + state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *resourceCrossAccountAttachment) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().GlobalAcceleratorConn(ctx) + + var state resourceCrossAccountAttachmentData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + input := &globalaccelerator.DeleteCrossAccountAttachmentInput{ + AttachmentArn: aws.String(state.ARN.ValueString()), + } + + _, err := conn.DeleteCrossAccountAttachmentWithContext(ctx, input) + + if err != nil { + var nfe *globalaccelerator.AttachmentNotFoundException + if errors.As(err, &nfe) { + return + } + resp.Diagnostics.AddError( + "Error deleting Global Accelerator CrossAccountAttachment", + fmt.Sprintf("Could not delete CrossAccountAttachment %s: %s", state.ARN.ValueString(), err), + ) + return + } +} + +func (r *resourceCrossAccountAttachment) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + conn := r.Meta().GlobalAcceleratorConn(ctx) + attachmentArn := req.ID + + output, err := conn.DescribeCrossAccountAttachment(&globalaccelerator.DescribeCrossAccountAttachmentInput{ + AttachmentArn: aws.String(attachmentArn), + }) + if err != nil { + resp.Diagnostics.AddError("Error describing CrossAccountAttachment", fmt.Sprintf("Could not describe CrossAccountAttachment with ARN %s: %s", attachmentArn, err)) + return + } + + if output == nil || output.CrossAccountAttachment == nil { + resp.Diagnostics.AddError("Error describing CrossAccountAttachment", fmt.Sprintf("CrossAccountAttachment with ARN %s not found", attachmentArn)) + return + } + + var plan resourceCrossAccountAttachmentData + plan.ARN = flex.StringToFramework(ctx, output.CrossAccountAttachment.AttachmentArn) + plan.ID = flex.StringToFramework(ctx, output.CrossAccountAttachment.AttachmentArn) + plan.Name = flex.StringToFramework(ctx, output.CrossAccountAttachment.Name) + + if output.CrossAccountAttachment.Principals != nil { + plan.Principals = flex.FlattenFrameworkStringList(ctx, output.CrossAccountAttachment.Principals) + } + if output.CrossAccountAttachment.Resources != nil { + resources, errDiags := flattenResources(ctx, output.CrossAccountAttachment.Resources) + if errDiags.HasError() { + resp.Diagnostics.Append(errDiags...) + return + } + plan.Resources = resources + } + + diags := resp.State.Set(ctx, &plan) + resp.Diagnostics.Append(diags...) + if diags.HasError() { + return + } +} + +var ResourceDataElementType = types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "endpoint_id": types.StringType, + "region": types.StringType, + }, +} + +func expandResources(tfList []ResourceData) []*globalaccelerator.Resource { + if len(tfList) == 0 { + return nil + } + + apiResources := make([]*globalaccelerator.Resource, len(tfList)) + + for i, tfResource := range tfList { + apiResource := &globalaccelerator.Resource{ + EndpointId: aws.String(tfResource.EndpointID.ValueString()), + } + + if !tfResource.Region.IsNull() && tfResource.Region.ValueString() != "" { + apiResource.Region = aws.String(tfResource.Region.ValueString()) + } + + apiResources[i] = apiResource + } + + return apiResources +} + +func flattenResources(ctx context.Context, resources []*globalaccelerator.Resource) (types.List, diag.Diagnostics) { + var diags diag.Diagnostics + + if resources == nil || len(resources) == 0 { + return types.ListNull(ResourceDataElementType), diags + } + + elems := []attr.Value{} + for _, resource := range resources { + endpointID := aws.StringValue(resource.EndpointId) + region := "" + // Extract the region from the ARN if the endpoint ID is an ARN + if strings.HasPrefix(endpointID, "arn:") { + parts := strings.Split(endpointID, ":") + if len(parts) > 3 { + region = parts[3] + } + } + + obj := map[string]attr.Value{ + "endpoint_id": types.StringValue(endpointID), + "region": types.StringValue(region), + } + objVal, d := types.ObjectValue(ResourceDataElementType.AttrTypes, obj) + diags.Append(d...) + + elems = append(elems, objVal) + } + + listVal, d := types.ListValue(ResourceDataElementType, elems) + diags.Append(d...) + + return listVal, diags +} + +func diffResources(ctx context.Context, oldList, newList types.List) (toAdd, toRemove []*globalaccelerator.Resource, diags diag.Diagnostics) { + toAdd = []*globalaccelerator.Resource{} + toRemove = []*globalaccelerator.Resource{} + var oldSlice, newSlice []ResourceData + + oldSlice, diags = convertListToResourceDataSlice(ctx, oldList) + if diags.HasError() { + return toAdd, toRemove, diags + } + + newSlice, diags = convertListToResourceDataSlice(ctx, newList) + if diags.HasError() { + return toAdd, toRemove, diags + } + + addSet, removeSet := diffResourceDataSlices(oldSlice, newSlice) + + for _, r := range addSet { + toAdd = append(toAdd, &globalaccelerator.Resource{ + EndpointId: r.EndpointId, + Region: r.Region, + }) + } + for _, r := range removeSet { + toRemove = append(toRemove, &globalaccelerator.Resource{ + EndpointId: r.EndpointId, + Region: r.Region, + }) + } + + return toAdd, toRemove, diags +} + +func convertListToResourceDataSlice(ctx context.Context, resourceList types.List) ([]ResourceData, diag.Diagnostics) { + var diags diag.Diagnostics + var resourceDataSlice []ResourceData + + if !resourceList.IsNull() { + diags := resourceList.ElementsAs(ctx, &resourceDataSlice, false) + if diags.HasError() { + return nil, diags + } + } + + return resourceDataSlice, diags +} + +func diffResourceDataSlices(oldSlice, newSlice []ResourceData) (toAdd, toRemove []*globalaccelerator.Resource) { + toRemoveMap := make(map[string]*globalaccelerator.Resource) + toAddMap := make(map[string]*globalaccelerator.Resource) + + for _, oldResource := range oldSlice { + key := generateCompositeKey(oldResource.EndpointID.ValueString(), oldResource.Region.ValueString()) + apiResource := &globalaccelerator.Resource{ + EndpointId: aws.String(oldResource.EndpointID.ValueString()), + } + if !oldResource.Region.IsNull() && oldResource.Region.ValueString() != "" { + apiResource.Region = aws.String(oldResource.Region.ValueString()) + } + toRemoveMap[key] = apiResource + } + + for _, newResource := range newSlice { + key := generateCompositeKey(newResource.EndpointID.ValueString(), newResource.Region.ValueString()) + apiResource := &globalaccelerator.Resource{ + EndpointId: aws.String(newResource.EndpointID.ValueString()), + } + if !newResource.Region.IsNull() && newResource.Region.ValueString() != "" { + apiResource.Region = aws.String(newResource.Region.ValueString()) + } + if _, found := toRemoveMap[key]; found { + delete(toRemoveMap, key) + } else { + toAddMap[key] = apiResource + } + } + + for _, resource := range toRemoveMap { + toRemove = append(toRemove, resource) + } + for _, resource := range toAddMap { + toAdd = append(toAdd, resource) + } + + return toAdd, toRemove +} + +func generateCompositeKey(endpointID, region string) string { + if region == "" { + region = "NO_REGION" // Special placeholder for resources without region + } + return endpointID + ":" + region +} + +func diffPrincipals(ctx context.Context, oldList, newList types.List) (toAdd, toRemove []*string, diags diag.Diagnostics) { + toAdd = []*string{} + toRemove = []*string{} + var oldSlice, newSlice []string + + if !oldList.IsNull() { + var oldElements []types.String + d := oldList.ElementsAs(ctx, &oldElements, false) + diags = append(diags, d...) + for _, element := range oldElements { + oldSlice = append(oldSlice, element.ValueString()) + } + } + + if !newList.IsNull() { + var newElements []types.String + d := newList.ElementsAs(ctx, &newElements, false) + diags = append(diags, d...) + for _, element := range newElements { + newSlice = append(newSlice, element.ValueString()) + } + } + + addSet, removeSet := diffSlices(oldSlice, newSlice) + + for elem := range addSet { + toAdd = append(toAdd, aws.String(elem)) + } + + for elem := range removeSet { + toRemove = append(toRemove, aws.String(elem)) + } + + return toAdd, toRemove, diags +} + +func diffSlices(oldSlice, newSlice []string) (toAdd, toRemove map[string]struct{}) { + toAdd = make(map[string]struct{}) + toRemove = make(map[string]struct{}) + + for _, s := range oldSlice { + toRemove[s] = struct{}{} + } + + for _, s := range newSlice { + if _, found := toRemove[s]; found { + delete(toRemove, s) + continue + } + toAdd[s] = struct{}{} + } + + return toAdd, toRemove +} + +type resourceCrossAccountAttachmentData struct { + ID types.String `tfsdk:"id"` + ARN types.String `tfsdk:"attachment_arn"` + Name types.String `tfsdk:"name"` + Principals types.List `tfsdk:"principals"` + Resources types.List `tfsdk:"resources"` + CreatedTime types.String `tfsdk:"created_time"` + LastModifiedTime types.String `tfsdk:"last_modified_time"` +} + +type ResourceData struct { + EndpointID types.String `tfsdk:"endpoint_id"` + Region types.String `tfsdk:"region"` +} diff --git a/internal/service/globalaccelerator/cross_account_attachment_test.go b/internal/service/globalaccelerator/cross_account_attachment_test.go new file mode 100644 index 00000000000..55e591589bb --- /dev/null +++ b/internal/service/globalaccelerator/cross_account_attachment_test.go @@ -0,0 +1,476 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package globalaccelerator_test + +import ( + "context" + "fmt" + "math/rand" + "reflect" + "strconv" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/globalaccelerator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + globalaccelerator_test "github.com/hashicorp/terraform-provider-aws/internal/service/globalaccelerator" +) + +func generateAccountID() string { + source := rand.NewSource(42) + rand := rand.New(source) + + accountID := "" + for i := 0; i < 12; i++ { + digit := rand.Intn(10) + accountID += strconv.Itoa(digit) + } + return accountID +} + +func TestExpandResources(t *testing.T) { + cases := []struct { + Input []globalaccelerator_test.ResourceData + ExpectedOutput []*globalaccelerator.Resource + }{ + { + Input: []globalaccelerator_test.ResourceData{}, + ExpectedOutput: nil, + }, + { + Input: []globalaccelerator_test.ResourceData{ + { + EndpointID: types.StringValue("endpoint-1"), + Region: types.StringValue("us-west-2"), + }, + { + EndpointID: types.StringValue("endpoint-2"), + Region: types.StringValue(""), + }, + }, + ExpectedOutput: []*globalaccelerator.Resource{ + { + EndpointId: aws.String("endpoint-1"), + Region: aws.String("us-west-2"), + }, + { + EndpointId: aws.String("endpoint-2"), + }, + }, + }, + } + + for _, tc := range cases { + output := globalaccelerator_test.ExpandResources(tc.Input) + if !reflect.DeepEqual(output, tc.ExpectedOutput) { + t.Fatalf("bad: expected %v, got %v", tc.ExpectedOutput, output) + } + } +} + +func TestFlattenResources(t *testing.T) { + elem := globalaccelerator_test.ResourceDataElementType + + endpoint1, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ + "endpoint_id": types.StringValue("arn:aws:ec2:us-west-2:171405876253:elastic-ip/eipalloc-1234567890abcdef0"), + "region": types.StringValue("us-west-2"), + }) + + expectedList, _ := types.ListValue(elem, []attr.Value{endpoint1}) + + testCases := []struct { + Name string + Input []*globalaccelerator.Resource + Expected types.List + }{ + { + Name: "empty input", + Input: []*globalaccelerator.Resource{}, + Expected: types.ListNull(elem), + }, + { + Name: "non-empty input", + Input: []*globalaccelerator.Resource{ + { + EndpointId: aws.String("arn:aws:ec2:us-west-2:171405876253:elastic-ip/eipalloc-1234567890abcdef0"), + Region: aws.String("us-west-2"), + }, + }, + Expected: expectedList, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + ctx := context.Background() + output, err := globalaccelerator_test.FlattenResources(ctx, tc.Input) + + if err != nil { + t.Fatalf("flattenResources() error = %v, wantErr %v", err, nil) + } + + if !reflect.DeepEqual(output, tc.Expected) { + t.Errorf("flattenResources() got = %v, want %v", output, tc.Expected) + } + }) + } +} + +func TestDiffResources(t *testing.T) { + ctx := context.Background() + elem := globalaccelerator_test.ResourceDataElementType + + endpoint1Object, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ + "endpoint_id": types.StringValue("endpoint-1"), + "region": types.StringValue("us-west-2"), + }) + endpoint2Object, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ + "endpoint_id": types.StringValue("endpoint-2"), + "region": types.StringValue("us-east-1"), + }) + + expectedResource1 := &globalaccelerator.Resource{ + EndpointId: aws.String("endpoint-1"), + Region: aws.String("us-west-2"), + } + expectedResource2 := &globalaccelerator.Resource{ + EndpointId: aws.String("endpoint-2"), + Region: aws.String("us-east-1"), + } + + cases := []struct { + Name string + OldList types.List + NewList types.List + ExpectedToAdd []*globalaccelerator.Resource + ExpectedToRemove []*globalaccelerator.Resource + }{ + { + Name: "EmptyLists", + OldList: types.ListNull(elem), + NewList: types.ListNull(elem), + ExpectedToAdd: []*globalaccelerator.Resource{}, + ExpectedToRemove: []*globalaccelerator.Resource{}, + }, + { + Name: "Resource to add", + OldList: types.ListValueMust(elem, []attr.Value{endpoint1Object}), + NewList: types.ListValueMust(elem, []attr.Value{endpoint1Object, endpoint2Object}), + ExpectedToAdd: []*globalaccelerator.Resource{ + expectedResource2, + }, + ExpectedToRemove: []*globalaccelerator.Resource{}, + }, + { + Name: "Resource to remove", + OldList: types.ListValueMust(elem, []attr.Value{endpoint1Object, endpoint2Object}), + NewList: types.ListValueMust(elem, []attr.Value{endpoint1Object}), + ExpectedToAdd: []*globalaccelerator.Resource{}, + ExpectedToRemove: []*globalaccelerator.Resource{ + expectedResource2, + }, + }, + { + Name: "Resource to add and remove", + OldList: types.ListValueMust(elem, []attr.Value{endpoint1Object}), + NewList: types.ListValueMust(elem, []attr.Value{endpoint2Object}), + ExpectedToAdd: []*globalaccelerator.Resource{ + expectedResource2, + }, + ExpectedToRemove: []*globalaccelerator.Resource{ + expectedResource1, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + toAdd, toRemove, _ := globalaccelerator_test.DiffResources(ctx, tc.OldList, tc.NewList) + + if !reflect.DeepEqual(toAdd, tc.ExpectedToAdd) { + t.Errorf("expected to add: %#v, got: %#v", tc.ExpectedToAdd, toAdd) + } + + if !reflect.DeepEqual(toRemove, tc.ExpectedToRemove) { + t.Errorf("expected to remove: %#v, got: %#v", tc.ExpectedToRemove, toRemove) + } + }) + } +} + +func TestDiffPrincipals(t *testing.T) { + ctx := context.Background() + + elemType := types.StringType + + principal1 := types.StringValue("principal-1") + principal2 := types.StringValue("principal-2") + + oldList, _ := types.ListValue(elemType, []attr.Value{principal1}) + newList, _ := types.ListValue(elemType, []attr.Value{principal2}) + + cases := []struct { + Name string + OldList types.List + NewList types.List + ExpectedToAdd []*string + ExpectedToRemove []*string + }{ + { + Name: "EmptyLists", + OldList: types.ListNull(elemType), + NewList: types.ListNull(elemType), + ExpectedToAdd: []*string{}, + ExpectedToRemove: []*string{}, + }, + { + Name: "NonEmptyLists", + OldList: oldList, + NewList: newList, + ExpectedToAdd: []*string{aws.String("principal-2")}, + ExpectedToRemove: []*string{aws.String("principal-1")}, + }, + } + + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + toAdd, toRemove, _ := globalaccelerator_test.DiffPrincipals(ctx, tc.OldList, tc.NewList) + + if !reflect.DeepEqual(toAdd, tc.ExpectedToAdd) { + t.Errorf("expected to add: %#v, got: %#v", tc.ExpectedToAdd, toAdd) + } + + if !reflect.DeepEqual(toRemove, tc.ExpectedToRemove) { + t.Errorf("expected to remove: %#v, got: %#v", tc.ExpectedToRemove, toRemove) + } + }) + } +} + +func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_globalaccelerator_cross_account_attachment.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var v *globalaccelerator.DescribeCrossAccountAttachmentOutput + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + // acctest.PreCheckPartitionHasService(t, "aws_globalaccelerator_cross_account_attachment") + }, + ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCrossAccountAttachmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} +func TestAccGlobalAcceleratorCrossAccountAttachment_principals(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_globalaccelerator_cross_account_attachment.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var v *globalaccelerator.DescribeCrossAccountAttachmentOutput + accountId := generateAccountID() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCrossAccountAttachmentConfig_principals(rName, accountId), + Check: resource.ComposeTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckTypeSetElemAttr(resourceName, "principals.*", accountId), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_globalaccelerator_cross_account_attachment.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + endpoint1 := "arn:aws:ec2:us-west-2:171405876253:elastic-ip/eipalloc-1234567890abcdef0" + endpoint2 := "arn:aws:ec2:us-east-1:171405876253:elastic-ip/eipalloc-1234567890abcdef1" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), + Steps: []resource.TestStep{ + { + + Config: testAccCrossAccountAttachmentConfig_resources(rName, []globalaccelerator_test.ResourceData{ + {EndpointID: types.StringValue(endpoint1), Region: types.StringValue(acctest.Region())}, + }), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ + "endpoint_id": endpoint1, + "region": acctest.Region(), + }), + ), + }, + { + Config: testAccCrossAccountAttachmentConfig_resources(rName, []globalaccelerator_test.ResourceData{ + {EndpointID: types.StringValue(endpoint1), Region: types.StringValue(acctest.Region())}, + {EndpointID: types.StringValue(endpoint2), Region: types.StringValue(acctest.AlternateRegion())}, + }), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ + "endpoint_id": endpoint1, + "region": acctest.Region(), + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ + "endpoint_id": endpoint2, + "region": acctest.AlternateRegion(), + }), + ), + }, + }, + }) +} + +func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_globalaccelerator_cross_account_attachment.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var v *globalaccelerator.DescribeCrossAccountAttachmentOutput + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + // acctest.PreCheckPartitionHasService(t, "aws_globalaccelerator_cross_account_attachment") + }, + ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCrossAccountAttachmentConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, globalaccelerator_test.ResourceCrossAccountAttachment, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckCrossAccountAttachmentDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_globalaccelerator_cross_account_attachment" { + continue + } + + _, err := conn.DescribeCrossAccountAttachment(&globalaccelerator.DescribeCrossAccountAttachmentInput{ + AttachmentArn: aws.String(rs.Primary.ID), + }) + if err != nil && strings.Contains(err.Error(), "AttachmentNotFoundException") { + return nil + } else if err != nil { + return fmt.Errorf("error checking if Global Accelerator Cross Account Attachment %s still exists: %s", rs.Primary.ID, err) + } + + return fmt.Errorf("Global Accelerator Cross Account Attachment %s still exists", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckCrossAccountAttachmentExists(ctx context.Context, resourceName string, v **globalaccelerator.DescribeCrossAccountAttachmentOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + + output, err := conn.DescribeCrossAccountAttachment(&globalaccelerator.DescribeCrossAccountAttachmentInput{ + AttachmentArn: aws.String(rs.Primary.ID), + }) + + if err != nil { + return err + } + + if output == nil || output.CrossAccountAttachment == nil { + return fmt.Errorf("Global Accelerator Cross Account Attachment %s does not exist", rs.Primary.ID) + } + + *v = output + + return nil + } +} + +func testAccCrossAccountAttachmentConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_globalaccelerator_cross_account_attachment" "test" { + name = %[1]q +} +`, rName) +} + +func testAccCrossAccountAttachmentConfig_principals(rName string, accountId string) string { + return fmt.Sprintf(` +resource "aws_globalaccelerator_cross_account_attachment" "test" { + name = %[1]q + principals = [%[2]q] +} +`, rName, accountId) +} + +func testAccCrossAccountAttachmentConfig_resources(rName string, resources []globalaccelerator_test.ResourceData) string { + var resourcesStr []string + for _, r := range resources { + resourcesStr = append(resourcesStr, fmt.Sprintf(`{ endpoint_id = "%s", region = "%s" }`, r.EndpointID.ValueString(), r.Region.ValueString())) + } + return fmt.Sprintf(` +resource "aws_globalaccelerator_cross_account_attachment" "test" { + name = "%s" + resources = [%s] +} +`, rName, strings.Join(resourcesStr, ", ")) +} diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go new file mode 100644 index 00000000000..e4f22b79e31 --- /dev/null +++ b/internal/service/globalaccelerator/exports_test.go @@ -0,0 +1,13 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package globalaccelerator + +// Exports for use in tests only. +var ( + ExpandResources = expandResources + FlattenResources = flattenResources + DiffResources = diffResources + DiffPrincipals = diffPrincipals + ResourceCrossAccountAttachment = newResourceCrossAccountAttachment +) diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index ee841fd98c6..7acc6f4288a 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -21,7 +21,12 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourceCrossAccountAttachment, + Name: "Cross Account Attachment", + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { diff --git a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown new file mode 100644 index 00000000000..16228e8e6a4 --- /dev/null +++ b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown @@ -0,0 +1,80 @@ +--- +subcategory: "Global Accelerator" +layout: "aws" +page_title: "AWS: aws_globalaccelerator_cross_account_attachment" +description: |- + Terraform resource for managing an AWS Global Accelerator Cross Account Attachment. +--- + +# Resource: aws_globalaccelerator_cross_account_attachment + +Terraform resource for managing an AWS Global Accelerator Cross Account Attachment. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_globalaccelerator_cross_account_attachment" "example" { + name = "example-cross-account-attachment" +} +``` + +### Usage with Optional Arguments + +```terraform +resource "aws_globalaccelerator_cross_account_attachment" "example" { + name = "example-cross-account-attachment" + principals = ["123456789012"] + resources = [ + { endpoint_id = "arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188", region = "us-west-2" }, + { endpoint_id = "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-other-load-balancer/50dc6c495c0c9189", region = "us-east-1" } + ] +} +``` + +## Argument Reference + +The following arguments are required: + +* `name` - (Required) Name of the Cross Account Attachment. + +The following arguments are optional: + +* `principals` - (Optional) List of AWS account IDs that are allowed to associate resources with the accelerator. +* `resources` - (Optional) List of resources to be associated with the accelerator. Each resource is specified as a map with keys `endpoint_id` and `region. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `arn` - ARN of the Cross Account Attachment. +* `id` - ID of the Cross Account Attachment. +* `created_time` - Creation Time when the Cross Account Attachment. +* `last_modified_time` - Last modified time of the Cross Account Attachment. +* + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) +* `update` - (Default `30m`) +* `delete` - (Default `30m`) + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Global Accelerator Cross Account Attachment using the `example_id_arg`. For example: + +```terraform +import { + to = aws_globalaccelerator_cross_account_attachment.example + id = "cross_account_attachment-id-12345678" +} +``` + +Using `terraform import`, import Global Accelerator Cross Account Attachment using the `example_id_arg`. For example: + +```console +% terraform import aws_globalaccelerator_cross_account_attachment.example cross_account_attachment-id-12345678 +``` From ec3ff8d5614697b85c2dff52145a2ee82ebe5b04 Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Mon, 26 Feb 2024 15:21:00 -0500 Subject: [PATCH 02/35] address feedback --- .../cross_account_attachment.go | 26 ++++++++----------- ...tor_cross_account_attachment.html.markdown | 7 +++-- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index 6f25ac678bf..b6ea32c34ac 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -7,16 +7,15 @@ import ( "context" "errors" "fmt" - "strings" "time" + "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/globalaccelerator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" @@ -65,16 +64,10 @@ func (r *resourceCrossAccountAttachment) Schema(ctx context.Context, req resourc "principals": schema.ListAttribute{ Optional: true, ElementType: types.StringType, - PlanModifiers: []planmodifier.List{ - listplanmodifier.RequiresReplace(), - }, }, "resources": schema.ListAttribute{ Optional: true, ElementType: ResourceDataElementType, - PlanModifiers: []planmodifier.List{ - listplanmodifier.RequiresReplace(), - }, }, "created_time": schema.StringAttribute{ Computed: true, @@ -133,8 +126,8 @@ func (r *resourceCrossAccountAttachment) Create(ctx context.Context, req resourc return } - plan.ID = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) state := plan + state.ID = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) state.ARN = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) state.CreatedTime = types.StringValue(out.CrossAccountAttachment.CreatedTime.Format(time.RFC3339)) @@ -178,6 +171,7 @@ func (r *resourceCrossAccountAttachment) Read(ctx context.Context, req resource. if out.CrossAccountAttachment.LastModifiedTime != nil { state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) } + state.Principals = flex.FlattenFrameworkStringList(ctx, out.CrossAccountAttachment.Principals) resources, errDiags := flattenResources(ctx, out.CrossAccountAttachment.Resources) resp.Diagnostics.Append(errDiags...) @@ -204,12 +198,12 @@ func (r *resourceCrossAccountAttachment) Update(ctx context.Context, req resourc var diags diag.Diagnostics if !plan.Principals.Equal(state.Principals) { - input.AddPrincipals, input.RemovePrincipals, diags = DiffPrincipals(ctx, state.Principals, plan.Principals) + input.AddPrincipals, input.RemovePrincipals, diags = diffPrincipals(ctx, state.Principals, plan.Principals) resp.Diagnostics.Append(diags...) } if !plan.Resources.Equal(state.Resources) { - input.AddResources, input.RemoveResources, diags = DiffResources(ctx, state.Resources, plan.Resources) + input.AddResources, input.RemoveResources, diags = diffResources(ctx, state.Resources, plan.Resources) resp.Diagnostics.Append(diags...) } @@ -346,11 +340,13 @@ func flattenResources(ctx context.Context, resources []*globalaccelerator.Resour endpointID := aws.StringValue(resource.EndpointId) region := "" // Extract the region from the ARN if the endpoint ID is an ARN - if strings.HasPrefix(endpointID, "arn:") { - parts := strings.Split(endpointID, ":") - if len(parts) > 3 { - region = parts[3] + if arn.IsARN(endpointID) { + parsedARN, err := arn.Parse(endpointID) + if err != nil { + diags.AddError("Error parsing ARN", err.Error()) + continue } + region = parsedARN.Region } obj := map[string]attr.Value{ diff --git a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown index 16228e8e6a4..ea7fea93126 100644 --- a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown +++ b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown @@ -42,7 +42,7 @@ The following arguments are required: The following arguments are optional: * `principals` - (Optional) List of AWS account IDs that are allowed to associate resources with the accelerator. -* `resources` - (Optional) List of resources to be associated with the accelerator. Each resource is specified as a map with keys `endpoint_id` and `region. +* `resources` - (Optional) List of resources to be associated with the accelerator. Each resource is specified as a map with keys `endpoint_id` and `region`. The `region` field is optional. ## Attribute Reference @@ -52,7 +52,6 @@ This resource exports the following attributes in addition to the arguments abov * `id` - ID of the Cross Account Attachment. * `created_time` - Creation Time when the Cross Account Attachment. * `last_modified_time` - Last modified time of the Cross Account Attachment. -* ## Timeouts @@ -69,12 +68,12 @@ In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashico ```terraform import { to = aws_globalaccelerator_cross_account_attachment.example - id = "cross_account_attachment-id-12345678" + id = "arn:aws:globalaccelerator::012345678910:attachment/01234567-abcd-8910-efgh-123456789012" } ``` Using `terraform import`, import Global Accelerator Cross Account Attachment using the `example_id_arg`. For example: ```console -% terraform import aws_globalaccelerator_cross_account_attachment.example cross_account_attachment-id-12345678 +% terraform import arn:aws:globalaccelerator::012345678910:attachment/01234567-abcd-8910-efgh-123456789012 ``` From 74f7d3cfcef344d047f80a3d83d06b057e290fea Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Tue, 27 Feb 2024 15:28:33 -0500 Subject: [PATCH 03/35] linter fixes --- .../cross_account_attachment.go | 4 +- .../cross_account_attachment_test.go | 73 ++++++++++++------- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index b6ea32c34ac..ba27de8f6ef 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -171,7 +171,7 @@ func (r *resourceCrossAccountAttachment) Read(ctx context.Context, req resource. if out.CrossAccountAttachment.LastModifiedTime != nil { state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) } - state.Principals = flex.FlattenFrameworkStringList(ctx, out.CrossAccountAttachment.Principals) + // state.Principals = flex.FlattenFrameworkStringList(ctx, out.CrossAccountAttachment.Principals) resources, errDiags := flattenResources(ctx, out.CrossAccountAttachment.Resources) resp.Diagnostics.Append(errDiags...) @@ -331,7 +331,7 @@ func expandResources(tfList []ResourceData) []*globalaccelerator.Resource { func flattenResources(ctx context.Context, resources []*globalaccelerator.Resource) (types.List, diag.Diagnostics) { var diags diag.Diagnostics - if resources == nil || len(resources) == 0 { + if len(resources) == 0 { return types.ListNull(ResourceDataElementType), diags } diff --git a/internal/service/globalaccelerator/cross_account_attachment_test.go b/internal/service/globalaccelerator/cross_account_attachment_test.go index 55e591589bb..dced5cedbcc 100644 --- a/internal/service/globalaccelerator/cross_account_attachment_test.go +++ b/internal/service/globalaccelerator/cross_account_attachment_test.go @@ -37,6 +37,7 @@ func generateAccountID() string { } func TestExpandResources(t *testing.T) { + t.Parallel() cases := []struct { Input []globalaccelerator_test.ResourceData ExpectedOutput []*globalaccelerator.Resource @@ -49,7 +50,7 @@ func TestExpandResources(t *testing.T) { Input: []globalaccelerator_test.ResourceData{ { EndpointID: types.StringValue("endpoint-1"), - Region: types.StringValue("us-west-2"), + Region: types.StringValue(acctest.Region()), }, { EndpointID: types.StringValue("endpoint-2"), @@ -59,7 +60,7 @@ func TestExpandResources(t *testing.T) { ExpectedOutput: []*globalaccelerator.Resource{ { EndpointId: aws.String("endpoint-1"), - Region: aws.String("us-west-2"), + Region: aws.String(acctest.Region()), }, { EndpointId: aws.String("endpoint-2"), @@ -77,11 +78,15 @@ func TestExpandResources(t *testing.T) { } func TestFlattenResources(t *testing.T) { + t.Parallel() elem := globalaccelerator_test.ResourceDataElementType + partition := acctest.Partition() + region := acctest.Region() + endpointID := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef0", partition, region) endpoint1, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ - "endpoint_id": types.StringValue("arn:aws:ec2:us-west-2:171405876253:elastic-ip/eipalloc-1234567890abcdef0"), - "region": types.StringValue("us-west-2"), + "endpoint_id": types.StringValue(endpointID), + "region": types.StringValue(region), }) expectedList, _ := types.ListValue(elem, []attr.Value{endpoint1}) @@ -100,8 +105,8 @@ func TestFlattenResources(t *testing.T) { Name: "non-empty input", Input: []*globalaccelerator.Resource{ { - EndpointId: aws.String("arn:aws:ec2:us-west-2:171405876253:elastic-ip/eipalloc-1234567890abcdef0"), - Region: aws.String("us-west-2"), + EndpointId: aws.String(endpointID), + Region: aws.String(region), }, }, Expected: expectedList, @@ -109,7 +114,9 @@ func TestFlattenResources(t *testing.T) { } for _, tc := range testCases { + tc := tc t.Run(tc.Name, func(t *testing.T) { + t.Parallel() ctx := context.Background() output, err := globalaccelerator_test.FlattenResources(ctx, tc.Input) @@ -125,25 +132,32 @@ func TestFlattenResources(t *testing.T) { } func TestDiffResources(t *testing.T) { + t.Parallel() ctx := context.Background() elem := globalaccelerator_test.ResourceDataElementType + partition := acctest.Partition() + region := acctest.Region() + alternateRegion := acctest.AlternateRegion() + endpointID := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef0", partition, region) + endpointID2 := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef1", partition, alternateRegion) + endpoint1Object, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ - "endpoint_id": types.StringValue("endpoint-1"), - "region": types.StringValue("us-west-2"), + "endpoint_id": types.StringValue(endpointID), + "region": types.StringValue(region), }) endpoint2Object, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ - "endpoint_id": types.StringValue("endpoint-2"), - "region": types.StringValue("us-east-1"), + "endpoint_id": types.StringValue(endpointID2), + "region": types.StringValue(alternateRegion), }) expectedResource1 := &globalaccelerator.Resource{ - EndpointId: aws.String("endpoint-1"), - Region: aws.String("us-west-2"), + EndpointId: aws.String(endpointID), + Region: aws.String(region), } expectedResource2 := &globalaccelerator.Resource{ - EndpointId: aws.String("endpoint-2"), - Region: aws.String("us-east-1"), + EndpointId: aws.String(endpointID2), + Region: aws.String(alternateRegion), } cases := []struct { @@ -192,7 +206,9 @@ func TestDiffResources(t *testing.T) { } for _, tc := range cases { + tc := tc t.Run(tc.Name, func(t *testing.T) { + t.Parallel() toAdd, toRemove, _ := globalaccelerator_test.DiffResources(ctx, tc.OldList, tc.NewList) if !reflect.DeepEqual(toAdd, tc.ExpectedToAdd) { @@ -207,6 +223,7 @@ func TestDiffResources(t *testing.T) { } func TestDiffPrincipals(t *testing.T) { + t.Parallel() ctx := context.Background() elemType := types.StringType @@ -241,7 +258,9 @@ func TestDiffPrincipals(t *testing.T) { } for _, tc := range cases { + tc := tc t.Run(tc.Name, func(t *testing.T) { + t.Parallel() toAdd, toRemove, _ := globalaccelerator_test.DiffPrincipals(ctx, tc.OldList, tc.NewList) if !reflect.DeepEqual(toAdd, tc.ExpectedToAdd) { @@ -323,8 +342,12 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - endpoint1 := "arn:aws:ec2:us-west-2:171405876253:elastic-ip/eipalloc-1234567890abcdef0" - endpoint2 := "arn:aws:ec2:us-east-1:171405876253:elastic-ip/eipalloc-1234567890abcdef1" + + partition := acctest.Partition() + region := acctest.Region() + alternateRegion := acctest.AlternateRegion() + endpointID := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef0", partition, region) + endpointID2 := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef1", partition, alternateRegion) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -337,28 +360,28 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { { Config: testAccCrossAccountAttachmentConfig_resources(rName, []globalaccelerator_test.ResourceData{ - {EndpointID: types.StringValue(endpoint1), Region: types.StringValue(acctest.Region())}, + {EndpointID: types.StringValue(endpointID), Region: types.StringValue(region)}, }), Check: resource.ComposeTestCheckFunc( resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ - "endpoint_id": endpoint1, - "region": acctest.Region(), + "endpoint_id": endpointID, + "region": region, }), ), }, { Config: testAccCrossAccountAttachmentConfig_resources(rName, []globalaccelerator_test.ResourceData{ - {EndpointID: types.StringValue(endpoint1), Region: types.StringValue(acctest.Region())}, - {EndpointID: types.StringValue(endpoint2), Region: types.StringValue(acctest.AlternateRegion())}, + {EndpointID: types.StringValue(endpointID), Region: types.StringValue(region)}, + {EndpointID: types.StringValue(endpointID2), Region: types.StringValue(alternateRegion)}, }), Check: resource.ComposeTestCheckFunc( resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ - "endpoint_id": endpoint1, - "region": acctest.Region(), + "endpoint_id": endpointID, + "region": region, }), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ - "endpoint_id": endpoint2, - "region": acctest.AlternateRegion(), + "endpoint_id": endpointID2, + "region": alternateRegion, }), ), }, From dc8b9c765eb575cc7c0aa99ea5c277da1dd1ccad Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Tue, 27 Feb 2024 15:44:14 -0500 Subject: [PATCH 04/35] comments, changelog --- .changelog/35991.text | 3 +++ .../globalaccelerator/cross_account_attachment.go | 3 ++- .../cross_account_attachment_test.go | 14 -------------- 3 files changed, 5 insertions(+), 15 deletions(-) create mode 100644 .changelog/35991.text diff --git a/.changelog/35991.text b/.changelog/35991.text new file mode 100644 index 00000000000..ceefbdd8350 --- /dev/null +++ b/.changelog/35991.text @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_globalaccelerator_cross_account_attachment +``` \ No newline at end of file diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index ba27de8f6ef..429debae92b 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -171,7 +171,8 @@ func (r *resourceCrossAccountAttachment) Read(ctx context.Context, req resource. if out.CrossAccountAttachment.LastModifiedTime != nil { state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) } - // state.Principals = flex.FlattenFrameworkStringList(ctx, out.CrossAccountAttachment.Principals) + + state.Principals = flex.FlattenFrameworkStringList(ctx, out.CrossAccountAttachment.Principals) resources, errDiags := flattenResources(ctx, out.CrossAccountAttachment.Resources) resp.Diagnostics.Append(errDiags...) diff --git a/internal/service/globalaccelerator/cross_account_attachment_test.go b/internal/service/globalaccelerator/cross_account_attachment_test.go index dced5cedbcc..e20acfab718 100644 --- a/internal/service/globalaccelerator/cross_account_attachment_test.go +++ b/internal/service/globalaccelerator/cross_account_attachment_test.go @@ -283,7 +283,6 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - // acctest.PreCheckPartitionHasService(t, "aws_globalaccelerator_cross_account_attachment") }, ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, @@ -357,18 +356,6 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ - { - - Config: testAccCrossAccountAttachmentConfig_resources(rName, []globalaccelerator_test.ResourceData{ - {EndpointID: types.StringValue(endpointID), Region: types.StringValue(region)}, - }), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ - "endpoint_id": endpointID, - "region": region, - }), - ), - }, { Config: testAccCrossAccountAttachmentConfig_resources(rName, []globalaccelerator_test.ResourceData{ {EndpointID: types.StringValue(endpointID), Region: types.StringValue(region)}, @@ -398,7 +385,6 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - // acctest.PreCheckPartitionHasService(t, "aws_globalaccelerator_cross_account_attachment") }, ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, From 6f0d6c697456f70b7a1caf3b32df2386c279d900 Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Wed, 3 Apr 2024 17:01:39 -0400 Subject: [PATCH 05/35] lint/semgrep --- .../service/globalaccelerator/cross_account_attachment.go | 4 ++-- .../globalaccelerator/cross_account_attachment_test.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index 429debae92b..be657b08ea3 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -150,7 +150,7 @@ func (r *resourceCrossAccountAttachment) Read(ctx context.Context, req resource. input := &globalaccelerator.DescribeCrossAccountAttachmentInput{ AttachmentArn: aws.String(state.ARN.ValueString()), } - out, err := conn.DescribeCrossAccountAttachment(input) + out, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, input) var nfe *globalaccelerator.AttachmentNotFoundException if errors.As(err, &nfe) { @@ -263,7 +263,7 @@ func (r *resourceCrossAccountAttachment) ImportState(ctx context.Context, req re conn := r.Meta().GlobalAcceleratorConn(ctx) attachmentArn := req.ID - output, err := conn.DescribeCrossAccountAttachment(&globalaccelerator.DescribeCrossAccountAttachmentInput{ + output, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DescribeCrossAccountAttachmentInput{ AttachmentArn: aws.String(attachmentArn), }) if err != nil { diff --git a/internal/service/globalaccelerator/cross_account_attachment_test.go b/internal/service/globalaccelerator/cross_account_attachment_test.go index e20acfab718..fe0f7bea9e0 100644 --- a/internal/service/globalaccelerator/cross_account_attachment_test.go +++ b/internal/service/globalaccelerator/cross_account_attachment_test.go @@ -411,7 +411,7 @@ func testAccCheckCrossAccountAttachmentDestroy(ctx context.Context) resource.Tes continue } - _, err := conn.DescribeCrossAccountAttachment(&globalaccelerator.DescribeCrossAccountAttachmentInput{ + _, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DescribeCrossAccountAttachmentInput{ AttachmentArn: aws.String(rs.Primary.ID), }) if err != nil && strings.Contains(err.Error(), "AttachmentNotFoundException") { @@ -436,7 +436,7 @@ func testAccCheckCrossAccountAttachmentExists(ctx context.Context, resourceName conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - output, err := conn.DescribeCrossAccountAttachment(&globalaccelerator.DescribeCrossAccountAttachmentInput{ + output, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DescribeCrossAccountAttachmentInput{ AttachmentArn: aws.String(rs.Primary.ID), }) @@ -457,7 +457,7 @@ func testAccCheckCrossAccountAttachmentExists(ctx context.Context, resourceName func testAccCrossAccountAttachmentConfig_basic(rName string) string { return fmt.Sprintf(` resource "aws_globalaccelerator_cross_account_attachment" "test" { - name = %[1]q + name = %[1]q } `, rName) } @@ -465,7 +465,7 @@ resource "aws_globalaccelerator_cross_account_attachment" "test" { func testAccCrossAccountAttachmentConfig_principals(rName string, accountId string) string { return fmt.Sprintf(` resource "aws_globalaccelerator_cross_account_attachment" "test" { - name = %[1]q + name = %[1]q principals = [%[2]q] } `, rName, accountId) From afe919848b0ab08de13b6016a5881a439648f303 Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Wed, 10 Apr 2024 12:54:02 -0400 Subject: [PATCH 06/35] naming, alphabetize feedback --- .../cross_account_attachment.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index be657b08ea3..ecdda10970d 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -53,8 +53,14 @@ func (r *resourceCrossAccountAttachment) Metadata(_ context.Context, req resourc func (r *resourceCrossAccountAttachment) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ - "attachment_arn": framework.ARNAttributeComputedOnly(), - "id": framework.IDAttribute(), + "arn": framework.ARNAttributeComputedOnly(), + "created_time": schema.StringAttribute{ + Computed: true, + }, + "id": framework.IDAttribute(), + "last_modified_time": schema.StringAttribute{ + Computed: true, + }, "name": schema.StringAttribute{ Required: true, PlanModifiers: []planmodifier.String{ @@ -69,12 +75,6 @@ func (r *resourceCrossAccountAttachment) Schema(ctx context.Context, req resourc Optional: true, ElementType: ResourceDataElementType, }, - "created_time": schema.StringAttribute{ - Computed: true, - }, - "last_modified_time": schema.StringAttribute{ - Computed: true, - }, }, } } @@ -517,7 +517,7 @@ func diffSlices(oldSlice, newSlice []string) (toAdd, toRemove map[string]struct{ type resourceCrossAccountAttachmentData struct { ID types.String `tfsdk:"id"` - ARN types.String `tfsdk:"attachment_arn"` + ARN types.String `tfsdk:"arn"` Name types.String `tfsdk:"name"` Principals types.List `tfsdk:"principals"` Resources types.List `tfsdk:"resources"` From b448a4816e7f5f104b4c602787f4fe9bc3175fac Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 14:17:41 -0400 Subject: [PATCH 07/35] Fix tfproviderdocs 'import section code block text should contain resource name: aws_globalaccelerator_cross_account_attachment'. --- .../r/globalaccelerator_cross_account_attachment.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown index ea7fea93126..1f843280598 100644 --- a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown +++ b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown @@ -75,5 +75,5 @@ import { Using `terraform import`, import Global Accelerator Cross Account Attachment using the `example_id_arg`. For example: ```console -% terraform import arn:aws:globalaccelerator::012345678910:attachment/01234567-abcd-8910-efgh-123456789012 +% terraform import aws_globalaccelerator_cross_account_attachment.example arn:aws:globalaccelerator::012345678910:attachment/01234567-abcd-8910-efgh-123456789012 ``` From 7961266c80470214de3cb24e6c7efaf1146fbe33 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 14:19:31 -0400 Subject: [PATCH 08/35] Fix markdown-lint 'MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]'. --- ...obalaccelerator_cross_account_attachment.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown index 1f843280598..3060be55796 100644 --- a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown +++ b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown @@ -20,7 +20,7 @@ resource "aws_globalaccelerator_cross_account_attachment" "example" { } ``` -### Usage with Optional Arguments +### Usage with Optional Arguments ```terraform resource "aws_globalaccelerator_cross_account_attachment" "example" { @@ -42,16 +42,16 @@ The following arguments are required: The following arguments are optional: * `principals` - (Optional) List of AWS account IDs that are allowed to associate resources with the accelerator. -* `resources` - (Optional) List of resources to be associated with the accelerator. Each resource is specified as a map with keys `endpoint_id` and `region`. The `region` field is optional. +* `resources` - (Optional) List of resources to be associated with the accelerator. Each resource is specified as a map with keys `endpoint_id` and `region`. The `region` field is optional. ## Attribute Reference This resource exports the following attributes in addition to the arguments above: -* `arn` - ARN of the Cross Account Attachment. +* `arn` - ARN of the Cross Account Attachment. * `id` - ID of the Cross Account Attachment. * `created_time` - Creation Time when the Cross Account Attachment. -* `last_modified_time` - Last modified time of the Cross Account Attachment. +* `last_modified_time` - Last modified time of the Cross Account Attachment. ## Timeouts From 174ff98e0b303a892eb14cf25a9c60debe2a3c45 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 15:03:04 -0400 Subject: [PATCH 09/35] 'internal/flex/Set' -> 'internal/types/Set'. --- internal/flex/flex.go | 18 ------------------ internal/service/ssm/document.go | 3 ++- internal/types/set.go | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 internal/types/set.go diff --git a/internal/flex/flex.go b/internal/flex/flex.go index 79407d007a3..05ba45d9d36 100644 --- a/internal/flex/flex.go +++ b/internal/flex/flex.go @@ -413,24 +413,6 @@ func ResourceIdPartCount(id string) int { return len(idParts) } -type Set[T comparable] []T - -// Difference find the elements in two sets that are not similar. -func (s Set[T]) Difference(ns Set[T]) Set[T] { - m := make(map[T]struct{}) - for _, v := range ns { - m[v] = struct{}{} - } - - var result []T - for _, v := range s { - if _, ok := m[v]; !ok { - result = append(result, v) - } - } - return result -} - // DiffStringMaps returns the set of keys and values that must be created, the set of keys // and values that must be destroyed, and the set of keys and values that are unchanged. func DiffStringMaps(oldMap, newMap map[string]interface{}) (map[string]*string, map[string]*string, map[string]*string) { diff --git a/internal/service/ssm/document.go b/internal/service/ssm/document.go index 425a0bfa4cb..8efb788b360 100644 --- a/internal/service/ssm/document.go +++ b/internal/service/ssm/document.go @@ -28,6 +28,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + itypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -403,7 +404,7 @@ func resourceDocumentUpdate(ctx context.Context, d *schema.ResourceData, meta in conn := meta.(*conns.AWSClient).SSMConn(ctx) if d.HasChange("permissions") { - var oldAccountIDs, newAccountIDs flex.Set[string] + var oldAccountIDs, newAccountIDs itypes.Set[string] o, n := d.GetChange("permissions") if v := o.(map[string]interface{}); len(v) > 0 { diff --git a/internal/types/set.go b/internal/types/set.go new file mode 100644 index 00000000000..c4bb73865e8 --- /dev/null +++ b/internal/types/set.go @@ -0,0 +1,22 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package types + +type Set[T comparable] []T + +// Difference find the elements in two sets that are not similar. +func (s Set[T]) Difference(ns Set[T]) Set[T] { + m := make(map[T]struct{}) + for _, v := range ns { + m[v] = struct{}{} + } + + var result []T + for _, v := range s { + if _, ok := m[v]; !ok { + result = append(result, v) + } + } + return result +} From f2eef3fc61be5859e391912aee9dca76c0fd497b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 15:13:42 -0400 Subject: [PATCH 10/35] Add 'TestSetDifference'. --- internal/types/set_test.go | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 internal/types/set_test.go diff --git a/internal/types/set_test.go b/internal/types/set_test.go new file mode 100644 index 00000000000..ac03701beb3 --- /dev/null +++ b/internal/types/set_test.go @@ -0,0 +1,65 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package types + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" +) + +func TestSetDifference(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + set1 Set[int] + set2 Set[int] + expected Set[int] + }{ + { + name: "nil sets", + expected: nil, + }, + { + name: "empty sets", + set1: Set[int]{}, + set2: Set[int]{}, + expected: nil, + }, + { + name: "no overlap", + set1: Set[int]{1, 3, 5, 7}, + set2: Set[int]{2, 4, 6, 8}, + expected: Set[int]{1, 3, 5, 7}, + }, + { + name: "no overlap swapped", + set1: Set[int]{2, 4, 6, 8}, + set2: Set[int]{1, 3, 5, 7}, + expected: Set[int]{2, 4, 6, 8}, + }, + { + name: "overlap", + set1: Set[int]{1, 2, 3, 4, 5, 7}, + set2: Set[int]{1, 2, 4, 6, 8}, + expected: Set[int]{3, 5, 7}, + }, + } + + for _, testCase := range testCases { + testCase := testCase + + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + got := testCase.set1.Difference(testCase.set2) + + if diff := cmp.Diff(got, testCase.expected, cmpopts.SortSlices(func(v1, v2 int) bool { return v1 < v2 })); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} From aacd972e0e47be54d2470b20dbb65ec3a4a2a7df Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 15:44:17 -0400 Subject: [PATCH 11/35] Complete 'internal/flex/Set' -> 'internal/types/Set'. --- internal/framework/flex/flex.go | 22 ----------- internal/framework/flex/flex_test.go | 59 ---------------------------- internal/framework/flex/set.go | 3 +- internal/framework/flex/set_test.go | 3 +- internal/types/set_test.go | 54 +++++++++++++++++++++++-- 5 files changed, 55 insertions(+), 86 deletions(-) delete mode 100644 internal/framework/flex/flex.go delete mode 100644 internal/framework/flex/flex_test.go diff --git a/internal/framework/flex/flex.go b/internal/framework/flex/flex.go deleted file mode 100644 index c15a5e76b93..00000000000 --- a/internal/framework/flex/flex.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package flex - -type Set[T comparable] []T - -// Difference find the elements in two sets that are not similar. -func (s Set[T]) Difference(ns Set[T]) Set[T] { - m := make(map[T]struct{}) - for _, v := range ns { - m[v] = struct{}{} - } - - var result []T - for _, v := range s { - if _, ok := m[v]; !ok { - result = append(result, v) - } - } - return result -} diff --git a/internal/framework/flex/flex_test.go b/internal/framework/flex/flex_test.go deleted file mode 100644 index c2143bf8efc..00000000000 --- a/internal/framework/flex/flex_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package flex - -import ( - "testing" - - "github.com/google/go-cmp/cmp" -) - -func TestSet_Difference_strings(t *testing.T) { - t.Parallel() - - type testCase struct { - original Set[string] - new Set[string] - expected Set[string] - } - tests := map[string]testCase{ - "nil": { - original: nil, - new: nil, - expected: nil, - }, - "equal": { - original: Set[string]{"one"}, - new: Set[string]{"one"}, - expected: nil, - }, - "difference": { - original: Set[string]{"one", "two", "four"}, - new: Set[string]{"one", "two", "three"}, - expected: Set[string]{"four"}, - }, - "difference_remove": { - original: Set[string]{"one", "two"}, - new: Set[string]{"one"}, - expected: Set[string]{"two"}, - }, - "difference_add": { - original: Set[string]{"one"}, - new: Set[string]{"one", "two"}, - expected: nil, - }, - } - - for name, test := range tests { - name, test := name, test - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := test.original.Difference(test.new) - if diff := cmp.Diff(got, test.expected); diff != "" { - t.Errorf("unexpected diff (+wanted, -got): %s", diff) - } - }) - } -} diff --git a/internal/framework/flex/set.go b/internal/framework/flex/set.go index f1665577d24..08b55107ba2 100644 --- a/internal/framework/flex/set.go +++ b/internal/framework/flex/set.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) func ExpandFrameworkStringSet(ctx context.Context, v basetypes.SetValuable) []*string { @@ -20,7 +21,7 @@ func ExpandFrameworkStringSet(ctx context.Context, v basetypes.SetValuable) []*s return output } -func ExpandFrameworkStringValueSet(ctx context.Context, v basetypes.SetValuable) Set[string] { +func ExpandFrameworkStringValueSet(ctx context.Context, v basetypes.SetValuable) itypes.Set[string] { var output []string must(Expand(ctx, v, &output)) diff --git a/internal/framework/flex/set_test.go b/internal/framework/flex/set_test.go index 9247e259191..74afc03eb14 100644 --- a/internal/framework/flex/set_test.go +++ b/internal/framework/flex/set_test.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) func TestExpandFrameworkStringSet(t *testing.T) { @@ -68,7 +69,7 @@ func TestExpandFrameworkStringValueSet(t *testing.T) { type testCase struct { input types.Set - expected flex.Set[string] + expected itypes.Set[string] } tests := map[string]testCase{ "null": { diff --git a/internal/types/set_test.go b/internal/types/set_test.go index ac03701beb3..7da36787a66 100644 --- a/internal/types/set_test.go +++ b/internal/types/set_test.go @@ -7,10 +7,9 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" ) -func TestSetDifference(t *testing.T) { +func TestSetDifference_ints(t *testing.T) { t.Parallel() testCases := []struct { @@ -57,7 +56,56 @@ func TestSetDifference(t *testing.T) { got := testCase.set1.Difference(testCase.set2) - if diff := cmp.Diff(got, testCase.expected, cmpopts.SortSlices(func(v1, v2 int) bool { return v1 < v2 })); diff != "" { + if diff := cmp.Diff(got, testCase.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestSetDifference_strings(t *testing.T) { + t.Parallel() + + type testCase struct { + original Set[string] + new Set[string] + expected Set[string] + } + tests := map[string]testCase{ + "nil": { + original: nil, + new: nil, + expected: nil, + }, + "equal": { + original: Set[string]{"one"}, + new: Set[string]{"one"}, + expected: nil, + }, + "difference": { + original: Set[string]{"one", "two", "four"}, + new: Set[string]{"one", "two", "three"}, + expected: Set[string]{"four"}, + }, + "difference_remove": { + original: Set[string]{"one", "two"}, + new: Set[string]{"one"}, + expected: Set[string]{"two"}, + }, + "difference_add": { + original: Set[string]{"one"}, + new: Set[string]{"one", "two"}, + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := test.original.Difference(test.new) + if diff := cmp.Diff(got, test.expected); diff != "" { t.Errorf("unexpected diff (+wanted, -got): %s", diff) } }) From 07f2d61b22ddaa7ae49bb24e6b9541ea9a3a6b36 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 16:26:20 -0400 Subject: [PATCH 12/35] Add 'flex.DiffSlices'. --- internal/flex/flex.go | 23 +++++++++++++++ internal/flex/flex_test.go | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/internal/flex/flex.go b/internal/flex/flex.go index 05ba45d9d36..f0301723438 100644 --- a/internal/flex/flex.go +++ b/internal/flex/flex.go @@ -5,6 +5,7 @@ package flex import ( "fmt" + "slices" "strconv" "strings" "time" @@ -460,3 +461,25 @@ func DiffStringValueMaps(oldMap, newMap map[string]interface{}) (map[string]stri return add, remove, unchanged } + +func DiffSlices[E any](old []E, new []E, eq func(E, E) bool) ([]E, []E, []E) { + // First, we're creating everything we have. + add := new + + // Build the slices of what to remove and what is unchanged. + remove := make([]E, 0) + unchanged := make([]E, 0) + for _, e := range old { + eq := func(v E) bool { return eq(v, e) } + if !slices.ContainsFunc(new, eq) { + // Delete it! + remove = append(remove, e) + } else { + unchanged = append(unchanged, e) + // Already present, so remove from new. + add = slices.DeleteFunc(add, eq) + } + } + + return add, remove, unchanged +} diff --git a/internal/flex/flex_test.go b/internal/flex/flex_test.go index 3e12ee7a578..e07c7c227db 100644 --- a/internal/flex/flex_test.go +++ b/internal/flex/flex_test.go @@ -466,3 +466,62 @@ func TestDiffStringValueMaps(t *testing.T) { } } } + +func TestDiffSlices(t *testing.T) { + t.Parallel() + + type x struct { + A string + B int + } + + cases := []struct { + Old, New []x + Create, Remove, Unchanged []x + }{ + // Add + { + Old: []x{{A: "foo", B: 1}}, + New: []x{{A: "foo", B: 1}, {A: "bar", B: 2}}, + Create: []x{{A: "bar", B: 2}}, + Remove: []x{}, + Unchanged: []x{{A: "foo", B: 1}}, + }, + // Modify + { + Old: []x{{A: "foo", B: 1}}, + New: []x{{A: "foo", B: 2}}, + Create: []x{{A: "foo", B: 2}}, + Remove: []x{{A: "foo", B: 1}}, + Unchanged: []x{}, + }, + // Overlap + { + Old: []x{{A: "foo", B: 1}, {A: "bar", B: 2}}, + New: []x{{A: "foo", B: 3}, {A: "bar", B: 2}}, + Create: []x{{A: "foo", B: 3}}, + Remove: []x{{A: "foo", B: 1}}, + Unchanged: []x{{A: "bar", B: 2}}, + }, + // Remove + { + Old: []x{{A: "foo", B: 1}, {A: "bar", B: 2}}, + New: []x{{A: "foo", B: 1}}, + Create: []x{}, + Remove: []x{{A: "bar", B: 2}}, + Unchanged: []x{{A: "foo", B: 1}}, + }, + } + for _, tc := range cases { + c, r, u := DiffSlices(tc.Old, tc.New, func(x1, x2 x) bool { return x1.A == x2.A && x1.B == x2.B }) + if diff := cmp.Diff(c, tc.Create); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + if diff := cmp.Diff(r, tc.Remove); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + if diff := cmp.Diff(u, tc.Unchanged); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + } +} From d5a1bf7a24a5919d628cd4eff3fea8d296d0a0ac Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 17:14:27 -0400 Subject: [PATCH 13/35] r/aws_globalaccelerator_cross_account_attachment: Tidy up. --- .../cross_account_attachment.go | 571 ++++++------------ .../cross_account_attachment_test.go | 345 ++--------- .../service/globalaccelerator/exports_test.go | 8 +- .../globalaccelerator/service_package_gen.go | 2 +- ...tor_cross_account_attachment.html.markdown | 2 + 5 files changed, 240 insertions(+), 688 deletions(-) diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index ecdda10970d..53cac2e989f 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -5,527 +5,322 @@ package globalaccelerator import ( "context" - "errors" "fmt" - "time" - "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/globalaccelerator" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" - "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag" + "github.com/hashicorp/terraform-provider-aws/internal/flex" "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" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkResource(name="Cross Account Attachment") -func newResourceCrossAccountAttachment(_ context.Context) (resource.ResourceWithConfigure, error) { - r := &resourceCrossAccountAttachment{} - - r.SetDefaultCreateTimeout(30 * time.Minute) - r.SetDefaultUpdateTimeout(30 * time.Minute) - r.SetDefaultDeleteTimeout(30 * time.Minute) +// @FrameworkResource(name="Cross-account Attachment") +// @Tags(identifierAttribute="id") +func newCrossAccountAttachmentResource(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &crossAccountAttachmentResource{} return r, nil } -const ( - ResNameCrossAccountAttachment = "Cross Account Attachment" -) - -type resourceCrossAccountAttachment struct { +type crossAccountAttachmentResource struct { framework.ResourceWithConfigure - framework.WithTimeouts + framework.WithImportByID } -func (r *resourceCrossAccountAttachment) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = "aws_globalaccelerator_cross_account_attachment" +func (*crossAccountAttachmentResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_globalaccelerator_cross_account_attachment" } -func (r *resourceCrossAccountAttachment) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (r *crossAccountAttachmentResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ - "arn": framework.ARNAttributeComputedOnly(), + names.AttrARN: framework.ARNAttributeComputedOnly(), "created_time": schema.StringAttribute{ - Computed: true, + CustomType: timetypes.RFC3339Type{}, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, }, - "id": framework.IDAttribute(), + names.AttrID: framework.IDAttribute(), "last_modified_time": schema.StringAttribute{ - Computed: true, + CustomType: timetypes.RFC3339Type{}, + Computed: true, }, "name": schema.StringAttribute{ Required: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), - }, }, - "principals": schema.ListAttribute{ + "principals": schema.SetAttribute{ + CustomType: fwtypes.SetOfStringType, Optional: true, ElementType: types.StringType, }, - "resources": schema.ListAttribute{ - Optional: true, - ElementType: ResourceDataElementType, + names.AttrTags: tftags.TagsAttribute(), + names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), + }, + Blocks: map[string]schema.Block{ + "resource": schema.SetNestedBlock{ + CustomType: fwtypes.NewSetNestedObjectTypeOf[resourceModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "endpoint_id": schema.StringAttribute{ + Optional: true, + }, + "region": schema.StringAttribute{ + Optional: true, + }, + }, + }, }, }, } } -func (r *resourceCrossAccountAttachment) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - conn := r.Meta().GlobalAcceleratorConn(ctx) - - var plan resourceCrossAccountAttachmentData - resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) - if resp.Diagnostics.HasError() { +func (r *crossAccountAttachmentResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var data crossAccountAttachmentResourceModel + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + if response.Diagnostics.HasError() { return } - input := &globalaccelerator.CreateCrossAccountAttachmentInput{ - IdempotencyToken: aws.String(id.UniqueId()), - Name: aws.String(plan.Name.ValueString()), - Tags: getTagsIn(ctx), - } + conn := r.Meta().GlobalAcceleratorConn(ctx) - if !plan.Principals.IsNull() { - input.Principals = flex.ExpandFrameworkStringList(ctx, plan.Principals) + input := &globalaccelerator.CreateCrossAccountAttachmentInput{} + response.Diagnostics.Append(fwflex.Expand(ctx, data, input)...) + if response.Diagnostics.HasError() { + return } - if !plan.Resources.IsNull() { - var tfResources []ResourceData - diags := plan.Resources.ElementsAs(ctx, &tfResources, false) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } + input.IdempotencyToken = aws.String(id.UniqueId()) + input.Tags = getTagsIn(ctx) - input.Resources = expandResources(tfResources) - } - - out, err := conn.CreateCrossAccountAttachmentWithContext(ctx, input) + output, err := conn.CreateCrossAccountAttachmentWithContext(ctx, input) if err != nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.GlobalAccelerator, create.ErrActionCreating, ResNameCrossAccountAttachment, plan.Name.String(), err), - err.Error(), - ) - return - } - if out == nil || out.CrossAccountAttachment == nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.GlobalAccelerator, create.ErrActionCreating, ResNameCrossAccountAttachment, plan.Name.String(), nil), - errors.New("empty output").Error(), - ) + response.Diagnostics.AddError("creating Global Accelerator Cross-account Attachment", err.Error()) + return } - state := plan - state.ID = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) - state.ARN = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) - - state.CreatedTime = types.StringValue(out.CrossAccountAttachment.CreatedTime.Format(time.RFC3339)) - if out.CrossAccountAttachment.LastModifiedTime != nil { - state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) - } + // Set values for unknowns. + data.AttachmentARN = fwflex.StringToFramework(ctx, output.CrossAccountAttachment.AttachmentArn) + data.CreatedTime = fwflex.TimeToFramework(ctx, output.CrossAccountAttachment.CreatedTime) + data.LastModifiedTime = fwflex.TimeToFramework(ctx, output.CrossAccountAttachment.LastModifiedTime) + data.setID() - resp.Diagnostics.Append(resp.State.Set(ctx, state)...) + response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -func (r *resourceCrossAccountAttachment) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - conn := r.Meta().GlobalAcceleratorConn(ctx) - - var state resourceCrossAccountAttachmentData - resp.Diagnostics.Append(req.State.Get(ctx, &state)...) - if resp.Diagnostics.HasError() { +func (r *crossAccountAttachmentResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var data crossAccountAttachmentResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { return } - input := &globalaccelerator.DescribeCrossAccountAttachmentInput{ - AttachmentArn: aws.String(state.ARN.ValueString()), - } - out, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, input) + if err := data.InitFromID(); err != nil { + response.Diagnostics.AddError("parsing resource ID", err.Error()) - var nfe *globalaccelerator.AttachmentNotFoundException - if errors.As(err, &nfe) { - resp.State.RemoveResource(ctx) - return - } - if err != nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.GlobalAccelerator, create.ErrActionSetting, ResNameCrossAccountAttachment, state.ID.String(), err), - err.Error(), - ) return } - state.ARN = flex.StringToFramework(ctx, out.CrossAccountAttachment.AttachmentArn) - state.Name = flex.StringToFramework(ctx, out.CrossAccountAttachment.Name) - state.CreatedTime = types.StringValue(out.CrossAccountAttachment.CreatedTime.Format(time.RFC3339)) - if out.CrossAccountAttachment.LastModifiedTime != nil { - state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) - } - - state.Principals = flex.FlattenFrameworkStringList(ctx, out.CrossAccountAttachment.Principals) - - resources, errDiags := flattenResources(ctx, out.CrossAccountAttachment.Resources) - resp.Diagnostics.Append(errDiags...) - if resp.Diagnostics.HasError() { - return - } - state.Resources = resources - resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) -} - -func (r *resourceCrossAccountAttachment) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { conn := r.Meta().GlobalAcceleratorConn(ctx) - var plan, state resourceCrossAccountAttachmentData - resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) - resp.Diagnostics.Append(req.State.Get(ctx, &state)...) - if resp.Diagnostics.HasError() { - return - } - - input := &globalaccelerator.UpdateCrossAccountAttachmentInput{ - AttachmentArn: aws.String(state.ARN.ValueString()), - } - - var diags diag.Diagnostics - if !plan.Principals.Equal(state.Principals) { - input.AddPrincipals, input.RemovePrincipals, diags = diffPrincipals(ctx, state.Principals, plan.Principals) - resp.Diagnostics.Append(diags...) - } - - if !plan.Resources.Equal(state.Resources) { - input.AddResources, input.RemoveResources, diags = diffResources(ctx, state.Resources, plan.Resources) - resp.Diagnostics.Append(diags...) - } - - if !plan.Name.Equal(state.Name) { - input.Name = aws.String(plan.Name.ValueString()) - } + output, err := findCrossAccountAttachmentByARN(ctx, conn, data.ID.ValueString()) - if input.Name != nil || input.AddPrincipals != nil || input.RemovePrincipals != nil || input.AddResources != nil || input.RemoveResources != nil { - out, err := conn.UpdateCrossAccountAttachmentWithContext(ctx, input) - if err != nil { - resp.Diagnostics.AddError( - "Error updating CrossAccountAttachment", - fmt.Sprintf("Could not update CrossAccountAttachment %s: %s", state.ARN.ValueString(), err), - ) - return - } + if tfresource.NotFound(err) { + response.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) + response.State.RemoveResource(ctx) - state.CreatedTime = types.StringValue(out.CrossAccountAttachment.CreatedTime.Format(time.RFC3339)) - if out.CrossAccountAttachment.LastModifiedTime != nil { - state.LastModifiedTime = types.StringValue(out.CrossAccountAttachment.LastModifiedTime.Format(time.RFC3339)) - } + return } - resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) -} - -func (r *resourceCrossAccountAttachment) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - conn := r.Meta().GlobalAcceleratorConn(ctx) + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("reading Global Accelerator Cross-account Attachment (%s)", data.ID.ValueString()), err.Error()) - var state resourceCrossAccountAttachmentData - resp.Diagnostics.Append(req.State.Get(ctx, &state)...) - if resp.Diagnostics.HasError() { return } - input := &globalaccelerator.DeleteCrossAccountAttachmentInput{ - AttachmentArn: aws.String(state.ARN.ValueString()), + // Normalize return value. + if data.Principals.IsNull() && len(output.Principals) == 0 { + output.Principals = nil } - _, err := conn.DeleteCrossAccountAttachmentWithContext(ctx, input) - - if err != nil { - var nfe *globalaccelerator.AttachmentNotFoundException - if errors.As(err, &nfe) { - return - } - resp.Diagnostics.AddError( - "Error deleting Global Accelerator CrossAccountAttachment", - fmt.Sprintf("Could not delete CrossAccountAttachment %s: %s", state.ARN.ValueString(), err), - ) + response.Diagnostics.Append(fwflex.Flatten(ctx, output, &data)...) + if response.Diagnostics.HasError() { return } -} -func (r *resourceCrossAccountAttachment) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - conn := r.Meta().GlobalAcceleratorConn(ctx) - attachmentArn := req.ID + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} - output, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DescribeCrossAccountAttachmentInput{ - AttachmentArn: aws.String(attachmentArn), - }) - if err != nil { - resp.Diagnostics.AddError("Error describing CrossAccountAttachment", fmt.Sprintf("Could not describe CrossAccountAttachment with ARN %s: %s", attachmentArn, err)) +func (r *crossAccountAttachmentResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var old, new crossAccountAttachmentResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &old)...) + if response.Diagnostics.HasError() { return } - - if output == nil || output.CrossAccountAttachment == nil { - resp.Diagnostics.AddError("Error describing CrossAccountAttachment", fmt.Sprintf("CrossAccountAttachment with ARN %s not found", attachmentArn)) + response.Diagnostics.Append(request.Plan.Get(ctx, &new)...) + if response.Diagnostics.HasError() { return } - var plan resourceCrossAccountAttachmentData - plan.ARN = flex.StringToFramework(ctx, output.CrossAccountAttachment.AttachmentArn) - plan.ID = flex.StringToFramework(ctx, output.CrossAccountAttachment.AttachmentArn) - plan.Name = flex.StringToFramework(ctx, output.CrossAccountAttachment.Name) + conn := r.Meta().GlobalAcceleratorConn(ctx) - if output.CrossAccountAttachment.Principals != nil { - plan.Principals = flex.FlattenFrameworkStringList(ctx, output.CrossAccountAttachment.Principals) - } - if output.CrossAccountAttachment.Resources != nil { - resources, errDiags := flattenResources(ctx, output.CrossAccountAttachment.Resources) - if errDiags.HasError() { - resp.Diagnostics.Append(errDiags...) - return + if !new.Name.Equal(old.Name) || + !new.Principals.Equal(old.Principals) || + !new.Resources.Equal(old.Resources) { + input := &globalaccelerator.UpdateCrossAccountAttachmentInput{ + AttachmentArn: fwflex.StringFromFramework(ctx, new.ID), } - plan.Resources = resources - } - diags := resp.State.Set(ctx, &plan) - resp.Diagnostics.Append(diags...) - if diags.HasError() { - return - } -} - -var ResourceDataElementType = types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "endpoint_id": types.StringType, - "region": types.StringType, - }, -} - -func expandResources(tfList []ResourceData) []*globalaccelerator.Resource { - if len(tfList) == 0 { - return nil - } - - apiResources := make([]*globalaccelerator.Resource, len(tfList)) - - for i, tfResource := range tfList { - apiResource := &globalaccelerator.Resource{ - EndpointId: aws.String(tfResource.EndpointID.ValueString()), + if !new.Name.Equal(old.Name) { + input.Name = aws.String(new.Name.ValueString()) } - if !tfResource.Region.IsNull() && tfResource.Region.ValueString() != "" { - apiResource.Region = aws.String(tfResource.Region.ValueString()) + if !new.Principals.Equal(old.Principals) { + oldPrincipals, newPrincipals := fwflex.ExpandFrameworkStringValueSet(ctx, old.Principals), fwflex.ExpandFrameworkStringValueSet(ctx, new.Principals) + input.AddPrincipals, input.RemovePrincipals = aws.StringSlice(newPrincipals.Difference(oldPrincipals)), aws.StringSlice(oldPrincipals.Difference(newPrincipals)) } - apiResources[i] = apiResource - } - - return apiResources -} + if !new.Resources.Equal(old.Resources) { + oldResources, diags := old.Resources.ToSlice(ctx) + response.Diagnostics.Append(diags...) + if response.Diagnostics.HasError() { + return + } -func flattenResources(ctx context.Context, resources []*globalaccelerator.Resource) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics + newResources, diags := new.Resources.ToSlice(ctx) + response.Diagnostics.Append(diags...) + if response.Diagnostics.HasError() { + return + } - if len(resources) == 0 { - return types.ListNull(ResourceDataElementType), diags - } + add, remove, _ := flex.DiffSlices(oldResources, newResources, func(v1, v2 *resourceModel) bool { + return v1.EndpointID.Equal(v2.EndpointID) && v1.Region.Equal(v2.Region) + }) - elems := []attr.Value{} - for _, resource := range resources { - endpointID := aws.StringValue(resource.EndpointId) - region := "" - // Extract the region from the ARN if the endpoint ID is an ARN - if arn.IsARN(endpointID) { - parsedARN, err := arn.Parse(endpointID) - if err != nil { - diags.AddError("Error parsing ARN", err.Error()) - continue + response.Diagnostics.Append(fwflex.Expand(ctx, add, input.AddResources)...) + if response.Diagnostics.HasError() { + return } - region = parsedARN.Region - } - obj := map[string]attr.Value{ - "endpoint_id": types.StringValue(endpointID), - "region": types.StringValue(region), + response.Diagnostics.Append(fwflex.Expand(ctx, remove, input.RemoveResources)...) + if response.Diagnostics.HasError() { + return + } } - objVal, d := types.ObjectValue(ResourceDataElementType.AttrTypes, obj) - diags.Append(d...) - - elems = append(elems, objVal) - } - - listVal, d := types.ListValue(ResourceDataElementType, elems) - diags.Append(d...) - - return listVal, diags -} -func diffResources(ctx context.Context, oldList, newList types.List) (toAdd, toRemove []*globalaccelerator.Resource, diags diag.Diagnostics) { - toAdd = []*globalaccelerator.Resource{} - toRemove = []*globalaccelerator.Resource{} - var oldSlice, newSlice []ResourceData + output, err := conn.UpdateCrossAccountAttachmentWithContext(ctx, input) - oldSlice, diags = convertListToResourceDataSlice(ctx, oldList) - if diags.HasError() { - return toAdd, toRemove, diags - } - - newSlice, diags = convertListToResourceDataSlice(ctx, newList) - if diags.HasError() { - return toAdd, toRemove, diags - } + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("updating Global Accelerator Cross-account Attachment (%s)", new.ID.ValueString()), err.Error()) - addSet, removeSet := diffResourceDataSlices(oldSlice, newSlice) + return + } - for _, r := range addSet { - toAdd = append(toAdd, &globalaccelerator.Resource{ - EndpointId: r.EndpointId, - Region: r.Region, - }) - } - for _, r := range removeSet { - toRemove = append(toRemove, &globalaccelerator.Resource{ - EndpointId: r.EndpointId, - Region: r.Region, - }) + new.LastModifiedTime = fwflex.TimeToFramework(ctx, output.CrossAccountAttachment.LastModifiedTime) + } else { + new.LastModifiedTime = old.LastModifiedTime } - return toAdd, toRemove, diags + response.Diagnostics.Append(response.State.Set(ctx, &new)...) } -func convertListToResourceDataSlice(ctx context.Context, resourceList types.List) ([]ResourceData, diag.Diagnostics) { - var diags diag.Diagnostics - var resourceDataSlice []ResourceData - - if !resourceList.IsNull() { - diags := resourceList.ElementsAs(ctx, &resourceDataSlice, false) - if diags.HasError() { - return nil, diags - } +func (r *crossAccountAttachmentResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data crossAccountAttachmentResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return } - return resourceDataSlice, diags -} + conn := r.Meta().GlobalAcceleratorConn(ctx) -func diffResourceDataSlices(oldSlice, newSlice []ResourceData) (toAdd, toRemove []*globalaccelerator.Resource) { - toRemoveMap := make(map[string]*globalaccelerator.Resource) - toAddMap := make(map[string]*globalaccelerator.Resource) + _, err := conn.DeleteCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DeleteCrossAccountAttachmentInput{ + AttachmentArn: fwflex.StringFromFramework(ctx, data.ID), + }) - for _, oldResource := range oldSlice { - key := generateCompositeKey(oldResource.EndpointID.ValueString(), oldResource.Region.ValueString()) - apiResource := &globalaccelerator.Resource{ - EndpointId: aws.String(oldResource.EndpointID.ValueString()), - } - if !oldResource.Region.IsNull() && oldResource.Region.ValueString() != "" { - apiResource.Region = aws.String(oldResource.Region.ValueString()) - } - toRemoveMap[key] = apiResource + if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAttachmentNotFoundException) { + return } - for _, newResource := range newSlice { - key := generateCompositeKey(newResource.EndpointID.ValueString(), newResource.Region.ValueString()) - apiResource := &globalaccelerator.Resource{ - EndpointId: aws.String(newResource.EndpointID.ValueString()), - } - if !newResource.Region.IsNull() && newResource.Region.ValueString() != "" { - apiResource.Region = aws.String(newResource.Region.ValueString()) - } - if _, found := toRemoveMap[key]; found { - delete(toRemoveMap, key) - } else { - toAddMap[key] = apiResource - } - } + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("deleting Global Accelerator Cross-account Attachment (%s)", data.ID.ValueString()), err.Error()) - for _, resource := range toRemoveMap { - toRemove = append(toRemove, resource) - } - for _, resource := range toAddMap { - toAdd = append(toAdd, resource) + return } +} - return toAdd, toRemove +func (r *crossAccountAttachmentResource) ModifyPlan(ctx context.Context, request resource.ModifyPlanRequest, response *resource.ModifyPlanResponse) { + r.SetTagsAll(ctx, request, response) } -func generateCompositeKey(endpointID, region string) string { - if region == "" { - region = "NO_REGION" // Special placeholder for resources without region +func findCrossAccountAttachmentByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.Attachment, error) { + input := &globalaccelerator.DescribeCrossAccountAttachmentInput{ + AttachmentArn: aws.String(arn), } - return endpointID + ":" + region + + return findCrossAccountAttachment(ctx, conn, input) } -func diffPrincipals(ctx context.Context, oldList, newList types.List) (toAdd, toRemove []*string, diags diag.Diagnostics) { - toAdd = []*string{} - toRemove = []*string{} - var oldSlice, newSlice []string - - if !oldList.IsNull() { - var oldElements []types.String - d := oldList.ElementsAs(ctx, &oldElements, false) - diags = append(diags, d...) - for _, element := range oldElements { - oldSlice = append(oldSlice, element.ValueString()) - } - } +func findCrossAccountAttachment(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeCrossAccountAttachmentInput) (*globalaccelerator.Attachment, error) { + output, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, input) - if !newList.IsNull() { - var newElements []types.String - d := newList.ElementsAs(ctx, &newElements, false) - diags = append(diags, d...) - for _, element := range newElements { - newSlice = append(newSlice, element.ValueString()) + if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAttachmentNotFoundException) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, } } - addSet, removeSet := diffSlices(oldSlice, newSlice) - - for elem := range addSet { - toAdd = append(toAdd, aws.String(elem)) + if err != nil { + return nil, err } - for elem := range removeSet { - toRemove = append(toRemove, aws.String(elem)) + if output == nil || output.CrossAccountAttachment == nil { + return nil, tfresource.NewEmptyResultError(input) } - return toAdd, toRemove, diags + return output.CrossAccountAttachment, nil } -func diffSlices(oldSlice, newSlice []string) (toAdd, toRemove map[string]struct{}) { - toAdd = make(map[string]struct{}) - toRemove = make(map[string]struct{}) - - for _, s := range oldSlice { - toRemove[s] = struct{}{} - } +type crossAccountAttachmentResourceModel struct { + AttachmentARN types.String `tfsdk:"arn"` + CreatedTime timetypes.RFC3339 `tfsdk:"created_time"` + ID types.String `tfsdk:"id"` + LastModifiedTime timetypes.RFC3339 `tfsdk:"last_modified_time"` + Name types.String `tfsdk:"name"` + Principals fwtypes.SetValueOf[types.String] `tfsdk:"principals"` + Resources fwtypes.SetNestedObjectValueOf[resourceModel] `tfsdk:"resource"` + Tags types.Map `tfsdk:"tags"` + TagsAll types.Map `tfsdk:"tags_all"` +} - for _, s := range newSlice { - if _, found := toRemove[s]; found { - delete(toRemove, s) - continue - } - toAdd[s] = struct{}{} - } +func (m *crossAccountAttachmentResourceModel) InitFromID() error { + m.AttachmentARN = m.ID - return toAdd, toRemove + return nil } -type resourceCrossAccountAttachmentData struct { - ID types.String `tfsdk:"id"` - ARN types.String `tfsdk:"arn"` - Name types.String `tfsdk:"name"` - Principals types.List `tfsdk:"principals"` - Resources types.List `tfsdk:"resources"` - CreatedTime types.String `tfsdk:"created_time"` - LastModifiedTime types.String `tfsdk:"last_modified_time"` +func (m *crossAccountAttachmentResourceModel) setID() { + m.ID = m.AttachmentARN } -type ResourceData struct { +type resourceModel struct { EndpointID types.String `tfsdk:"endpoint_id"` Region types.String `tfsdk:"region"` } diff --git a/internal/service/globalaccelerator/cross_account_attachment_test.go b/internal/service/globalaccelerator/cross_account_attachment_test.go index fe0f7bea9e0..a4e175a423a 100644 --- a/internal/service/globalaccelerator/cross_account_attachment_test.go +++ b/internal/service/globalaccelerator/cross_account_attachment_test.go @@ -6,279 +6,24 @@ package globalaccelerator_test import ( "context" "fmt" - "math/rand" - "reflect" - "strconv" - "strings" "testing" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/globalaccelerator" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" - globalaccelerator_test "github.com/hashicorp/terraform-provider-aws/internal/service/globalaccelerator" + tfglobalaccelerator "github.com/hashicorp/terraform-provider-aws/internal/service/globalaccelerator" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -func generateAccountID() string { - source := rand.NewSource(42) - rand := rand.New(source) - - accountID := "" - for i := 0; i < 12; i++ { - digit := rand.Intn(10) - accountID += strconv.Itoa(digit) - } - return accountID -} - -func TestExpandResources(t *testing.T) { - t.Parallel() - cases := []struct { - Input []globalaccelerator_test.ResourceData - ExpectedOutput []*globalaccelerator.Resource - }{ - { - Input: []globalaccelerator_test.ResourceData{}, - ExpectedOutput: nil, - }, - { - Input: []globalaccelerator_test.ResourceData{ - { - EndpointID: types.StringValue("endpoint-1"), - Region: types.StringValue(acctest.Region()), - }, - { - EndpointID: types.StringValue("endpoint-2"), - Region: types.StringValue(""), - }, - }, - ExpectedOutput: []*globalaccelerator.Resource{ - { - EndpointId: aws.String("endpoint-1"), - Region: aws.String(acctest.Region()), - }, - { - EndpointId: aws.String("endpoint-2"), - }, - }, - }, - } - - for _, tc := range cases { - output := globalaccelerator_test.ExpandResources(tc.Input) - if !reflect.DeepEqual(output, tc.ExpectedOutput) { - t.Fatalf("bad: expected %v, got %v", tc.ExpectedOutput, output) - } - } -} - -func TestFlattenResources(t *testing.T) { - t.Parallel() - elem := globalaccelerator_test.ResourceDataElementType - partition := acctest.Partition() - region := acctest.Region() - endpointID := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef0", partition, region) - - endpoint1, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ - "endpoint_id": types.StringValue(endpointID), - "region": types.StringValue(region), - }) - - expectedList, _ := types.ListValue(elem, []attr.Value{endpoint1}) - - testCases := []struct { - Name string - Input []*globalaccelerator.Resource - Expected types.List - }{ - { - Name: "empty input", - Input: []*globalaccelerator.Resource{}, - Expected: types.ListNull(elem), - }, - { - Name: "non-empty input", - Input: []*globalaccelerator.Resource{ - { - EndpointId: aws.String(endpointID), - Region: aws.String(region), - }, - }, - Expected: expectedList, - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.Name, func(t *testing.T) { - t.Parallel() - ctx := context.Background() - output, err := globalaccelerator_test.FlattenResources(ctx, tc.Input) - - if err != nil { - t.Fatalf("flattenResources() error = %v, wantErr %v", err, nil) - } - - if !reflect.DeepEqual(output, tc.Expected) { - t.Errorf("flattenResources() got = %v, want %v", output, tc.Expected) - } - }) - } -} - -func TestDiffResources(t *testing.T) { - t.Parallel() - ctx := context.Background() - elem := globalaccelerator_test.ResourceDataElementType - - partition := acctest.Partition() - region := acctest.Region() - alternateRegion := acctest.AlternateRegion() - endpointID := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef0", partition, region) - endpointID2 := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef1", partition, alternateRegion) - - endpoint1Object, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ - "endpoint_id": types.StringValue(endpointID), - "region": types.StringValue(region), - }) - endpoint2Object, _ := types.ObjectValue(elem.AttrTypes, map[string]attr.Value{ - "endpoint_id": types.StringValue(endpointID2), - "region": types.StringValue(alternateRegion), - }) - - expectedResource1 := &globalaccelerator.Resource{ - EndpointId: aws.String(endpointID), - Region: aws.String(region), - } - expectedResource2 := &globalaccelerator.Resource{ - EndpointId: aws.String(endpointID2), - Region: aws.String(alternateRegion), - } - - cases := []struct { - Name string - OldList types.List - NewList types.List - ExpectedToAdd []*globalaccelerator.Resource - ExpectedToRemove []*globalaccelerator.Resource - }{ - { - Name: "EmptyLists", - OldList: types.ListNull(elem), - NewList: types.ListNull(elem), - ExpectedToAdd: []*globalaccelerator.Resource{}, - ExpectedToRemove: []*globalaccelerator.Resource{}, - }, - { - Name: "Resource to add", - OldList: types.ListValueMust(elem, []attr.Value{endpoint1Object}), - NewList: types.ListValueMust(elem, []attr.Value{endpoint1Object, endpoint2Object}), - ExpectedToAdd: []*globalaccelerator.Resource{ - expectedResource2, - }, - ExpectedToRemove: []*globalaccelerator.Resource{}, - }, - { - Name: "Resource to remove", - OldList: types.ListValueMust(elem, []attr.Value{endpoint1Object, endpoint2Object}), - NewList: types.ListValueMust(elem, []attr.Value{endpoint1Object}), - ExpectedToAdd: []*globalaccelerator.Resource{}, - ExpectedToRemove: []*globalaccelerator.Resource{ - expectedResource2, - }, - }, - { - Name: "Resource to add and remove", - OldList: types.ListValueMust(elem, []attr.Value{endpoint1Object}), - NewList: types.ListValueMust(elem, []attr.Value{endpoint2Object}), - ExpectedToAdd: []*globalaccelerator.Resource{ - expectedResource2, - }, - ExpectedToRemove: []*globalaccelerator.Resource{ - expectedResource1, - }, - }, - } - - for _, tc := range cases { - tc := tc - t.Run(tc.Name, func(t *testing.T) { - t.Parallel() - toAdd, toRemove, _ := globalaccelerator_test.DiffResources(ctx, tc.OldList, tc.NewList) - - if !reflect.DeepEqual(toAdd, tc.ExpectedToAdd) { - t.Errorf("expected to add: %#v, got: %#v", tc.ExpectedToAdd, toAdd) - } - - if !reflect.DeepEqual(toRemove, tc.ExpectedToRemove) { - t.Errorf("expected to remove: %#v, got: %#v", tc.ExpectedToRemove, toRemove) - } - }) - } -} - -func TestDiffPrincipals(t *testing.T) { - t.Parallel() - ctx := context.Background() - - elemType := types.StringType - - principal1 := types.StringValue("principal-1") - principal2 := types.StringValue("principal-2") - - oldList, _ := types.ListValue(elemType, []attr.Value{principal1}) - newList, _ := types.ListValue(elemType, []attr.Value{principal2}) - - cases := []struct { - Name string - OldList types.List - NewList types.List - ExpectedToAdd []*string - ExpectedToRemove []*string - }{ - { - Name: "EmptyLists", - OldList: types.ListNull(elemType), - NewList: types.ListNull(elemType), - ExpectedToAdd: []*string{}, - ExpectedToRemove: []*string{}, - }, - { - Name: "NonEmptyLists", - OldList: oldList, - NewList: newList, - ExpectedToAdd: []*string{aws.String("principal-2")}, - ExpectedToRemove: []*string{aws.String("principal-1")}, - }, - } - - for _, tc := range cases { - tc := tc - t.Run(tc.Name, func(t *testing.T) { - t.Parallel() - toAdd, toRemove, _ := globalaccelerator_test.DiffPrincipals(ctx, tc.OldList, tc.NewList) - - if !reflect.DeepEqual(toAdd, tc.ExpectedToAdd) { - t.Errorf("expected to add: %#v, got: %#v", tc.ExpectedToAdd, toAdd) - } - - if !reflect.DeepEqual(toRemove, tc.ExpectedToRemove) { - t.Errorf("expected to remove: %#v, got: %#v", tc.ExpectedToRemove, toRemove) - } - }) - } -} - func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var v *globalaccelerator.DescribeCrossAccountAttachmentOutput + rName1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var v globalaccelerator.Attachment resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -289,10 +34,16 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCrossAccountAttachmentConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Config: testAccCrossAccountAttachmentConfig_basic(rName1), + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), - resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckResourceAttr(resourceName, "name", rName1), + resource.TestCheckResourceAttr(resourceName, "principals.#", "0"), + resource.TestCheckResourceAttr(resourceName, "resource.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, { @@ -300,6 +51,13 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccCrossAccountAttachmentConfig_basic(rName2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + ), + }, }, }) } @@ -307,8 +65,8 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_principals(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var v *globalaccelerator.DescribeCrossAccountAttachmentOutput - accountId := generateAccountID() + var v globalaccelerator.Attachment + rAccountID := sdkacctest.RandStringFromCharSet(12, "012346789") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -319,13 +77,13 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_principals(t *testing.T) { CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCrossAccountAttachmentConfig_principals(rName, accountId), + Config: testAccCrossAccountAttachmentConfig_principals(rName, rAccountID), Check: resource.ComposeTestCheckFunc( testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckTypeSetElemAttr(resourceName, "principals.*", accountId), resource.TestCheckResourceAttrSet(resourceName, "created_time"), resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckTypeSetElemAttr(resourceName, "principals.*", rAccountID), + resource.TestCheckResourceAttr(resourceName, "name", rName), ), }, { @@ -337,11 +95,11 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_principals(t *testing.T) { }) } +/* func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - partition := acctest.Partition() region := acctest.Region() alternateRegion := acctest.AlternateRegion() @@ -357,7 +115,7 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCrossAccountAttachmentConfig_resources(rName, []globalaccelerator_test.ResourceData{ + Config: testAccCrossAccountAttachmentConfig_resources(rName, []tfglobalaccelerator.ResourceData{ {EndpointID: types.StringValue(endpointID), Region: types.StringValue(region)}, {EndpointID: types.StringValue(endpointID2), Region: types.StringValue(alternateRegion)}, }), @@ -375,12 +133,14 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { }, }) } +*/ +// TODO: tags func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var v *globalaccelerator.DescribeCrossAccountAttachmentOutput + var v globalaccelerator.Attachment resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -394,7 +154,7 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { Config: testAccCrossAccountAttachmentConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), - acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, globalaccelerator_test.ResourceCrossAccountAttachment, resourceName), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfglobalaccelerator.ResourceCrossAccountAttachment, resourceName), ), ExpectNonEmptyPlan: true, }, @@ -411,44 +171,39 @@ func testAccCheckCrossAccountAttachmentDestroy(ctx context.Context) resource.Tes continue } - _, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DescribeCrossAccountAttachmentInput{ - AttachmentArn: aws.String(rs.Primary.ID), - }) - if err != nil && strings.Contains(err.Error(), "AttachmentNotFoundException") { - return nil - } else if err != nil { - return fmt.Errorf("error checking if Global Accelerator Cross Account Attachment %s still exists: %s", rs.Primary.ID, err) + _, err := tfglobalaccelerator.FindCrossAccountAttachmentByARN(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err } - return fmt.Errorf("Global Accelerator Cross Account Attachment %s still exists", rs.Primary.ID) + return fmt.Errorf("Global Accelerator ross-account Attachment %s still exists", rs.Primary.ID) } return nil } } -func testAccCheckCrossAccountAttachmentExists(ctx context.Context, resourceName string, v **globalaccelerator.DescribeCrossAccountAttachmentOutput) resource.TestCheckFunc { +func testAccCheckCrossAccountAttachmentExists(ctx context.Context, n string, v *globalaccelerator.Attachment) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", resourceName) + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - output, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DescribeCrossAccountAttachmentInput{ - AttachmentArn: aws.String(rs.Primary.ID), - }) + output, err := tfglobalaccelerator.FindCrossAccountAttachmentByARN(ctx, conn, rs.Primary.ID) if err != nil { return err } - if output == nil || output.CrossAccountAttachment == nil { - return fmt.Errorf("Global Accelerator Cross Account Attachment %s does not exist", rs.Primary.ID) - } - - *v = output + *v = *output return nil } @@ -462,16 +217,17 @@ resource "aws_globalaccelerator_cross_account_attachment" "test" { `, rName) } -func testAccCrossAccountAttachmentConfig_principals(rName string, accountId string) string { +func testAccCrossAccountAttachmentConfig_principals(rName string, accountID string) string { return fmt.Sprintf(` resource "aws_globalaccelerator_cross_account_attachment" "test" { name = %[1]q principals = [%[2]q] } -`, rName, accountId) +`, rName, accountID) } -func testAccCrossAccountAttachmentConfig_resources(rName string, resources []globalaccelerator_test.ResourceData) string { +/* +func testAccCrossAccountAttachmentConfig_resources(rName string, resources []tfglobalaccelerator.ResourceData) string { var resourcesStr []string for _, r := range resources { resourcesStr = append(resourcesStr, fmt.Sprintf(`{ endpoint_id = "%s", region = "%s" }`, r.EndpointID.ValueString(), r.Region.ValueString())) @@ -483,3 +239,4 @@ resource "aws_globalaccelerator_cross_account_attachment" "test" { } `, rName, strings.Join(resourcesStr, ", ")) } +*/ diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index e4f22b79e31..4d8047be515 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -5,9 +5,7 @@ package globalaccelerator // Exports for use in tests only. var ( - ExpandResources = expandResources - FlattenResources = flattenResources - DiffResources = diffResources - DiffPrincipals = diffPrincipals - ResourceCrossAccountAttachment = newResourceCrossAccountAttachment + ResourceCrossAccountAttachment = newCrossAccountAttachmentResource + + FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN ) diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index 7acc6f4288a..02ac07ab0f8 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -23,7 +23,7 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { return []*types.ServicePackageFrameworkResource{ { - Factory: newResourceCrossAccountAttachment, + Factory: newCrossAccountAttachmentResource, Name: "Cross Account Attachment", }, } diff --git a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown index 3060be55796..bb7c718a92b 100644 --- a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown +++ b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown @@ -43,6 +43,7 @@ The following arguments are optional: * `principals` - (Optional) List of AWS account IDs that are allowed to associate resources with the accelerator. * `resources` - (Optional) List of resources to be associated with the accelerator. Each resource is specified as a map with keys `endpoint_id` and `region`. The `region` field is optional. +* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ## Attribute Reference @@ -52,6 +53,7 @@ This resource exports the following attributes in addition to the arguments abov * `id` - ID of the Cross Account Attachment. * `created_time` - Creation Time when the Cross Account Attachment. * `last_modified_time` - Last modified time of the Cross Account Attachment. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). ## Timeouts From 50c597935c3d62c2b883b0e70d39bff0255bec5a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 17:14:42 -0400 Subject: [PATCH 14/35] Acceptance test output: % make testacc TESTARGS='-run=TestAccGlobalAcceleratorCrossAccountAttachment_basic' PKG=globalaccelerator ==> Checking that code complies with gofmt requirements... TF_ACC=1 go1.22.2 test ./internal/service/globalaccelerator/... -v -count 1 -parallel 20 -run=TestAccGlobalAcceleratorCrossAccountAttachment_basic -timeout 360m === RUN TestAccGlobalAcceleratorCrossAccountAttachment_basic === PAUSE TestAccGlobalAcceleratorCrossAccountAttachment_basic === CONT TestAccGlobalAcceleratorCrossAccountAttachment_basic --- PASS: TestAccGlobalAcceleratorCrossAccountAttachment_basic (30.41s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/globalaccelerator 41.164s From 9ba8e78134783b06448e0c32e28a4cc354eeb5f2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 22 Apr 2024 17:15:14 -0400 Subject: [PATCH 15/35] Correct CHANGELOG entry file name. --- .changelog/{35991.text => 35991.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{35991.text => 35991.txt} (100%) diff --git a/.changelog/35991.text b/.changelog/35991.txt similarity index 100% rename from .changelog/35991.text rename to .changelog/35991.txt From 987e1b365abd162ba7e90373ba4eb85ffadd6dd2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 10:23:19 -0400 Subject: [PATCH 16/35] aws_eip: Add 'arn' attribute. --- .changelog/35991.txt | 8 ++++++++ internal/service/ec2/ec2_eip.go | 19 ++++++++++++++++++- internal/service/ec2/ec2_eip_data_source.go | 9 ++++++++- .../service/ec2/ec2_eip_data_source_test.go | 1 + internal/service/ec2/ec2_eip_test.go | 1 + 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.changelog/35991.txt b/.changelog/35991.txt index ceefbdd8350..951446948bc 100644 --- a/.changelog/35991.txt +++ b/.changelog/35991.txt @@ -1,3 +1,11 @@ ```release-note:new-resource aws_globalaccelerator_cross_account_attachment +``` + +```release-note:enhancement +resource/aws_eip: Add `arn` attribute +``` + +```release-note:enhancement +data-source/aws_eip: Add `arn` attribute ``` \ No newline at end of file diff --git a/internal/service/ec2/ec2_eip.go b/internal/service/ec2/ec2_eip.go index 1476bd416f3..2d143005c78 100644 --- a/internal/service/ec2/ec2_eip.go +++ b/internal/service/ec2/ec2_eip.go @@ -12,6 +12,7 @@ import ( "time" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" @@ -57,6 +58,10 @@ func resourceEIP() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, "associate_with_private_ip": { Type: schema.TypeString, Optional: true, @@ -226,7 +231,9 @@ func resourceEIPRead(ctx context.Context, d *schema.ResourceData, meta interface } address := outputRaw.(*types.Address) - d.Set("allocation_id", address.AllocationId) + allocationID := aws.ToString(address.AllocationId) + d.Set("allocation_id", allocationID) + d.Set("arn", eipARN(meta.(*conns.AWSClient), allocationID)) d.Set("association_id", address.AssociationId) d.Set("carrier_ip", address.CarrierIp) d.Set("customer_owned_ip", address.CustomerOwnedIp) @@ -405,3 +412,13 @@ func disassociateEIP(ctx context.Context, conn *ec2.Client, associationID string return nil } + +func eipARN(c *conns.AWSClient, allocationID string) string { + return arn.ARN{ + Partition: c.Partition, + Service: names.EC2, + Region: c.Region, + AccountID: c.AccountID, + Resource: "elastic-ip/" + allocationID, + }.String() +} diff --git a/internal/service/ec2/ec2_eip_data_source.go b/internal/service/ec2/ec2_eip_data_source.go index d919acc9252..2949716431a 100644 --- a/internal/service/ec2/ec2_eip_data_source.go +++ b/internal/service/ec2/ec2_eip_data_source.go @@ -30,6 +30,10 @@ func dataSourceEIP() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, "association_id": { Type: schema.TypeString, Computed: true, @@ -132,7 +136,9 @@ func dataSourceEIPRead(ctx context.Context, d *schema.ResourceData, meta interfa } if eip.Domain == types.DomainTypeVpc { - d.SetId(aws.ToString(eip.AllocationId)) + allocationID := aws.ToString(eip.AllocationId) + d.SetId(allocationID) + d.Set("arn", eipARN(meta.(*conns.AWSClient), allocationID)) addressAttr, err := findEIPDomainNameAttributeByAllocationID(ctx, conn, d.Id()) @@ -146,6 +152,7 @@ func dataSourceEIPRead(ctx context.Context, d *schema.ResourceData, meta interfa } } else { d.SetId(aws.ToString(eip.PublicIp)) + d.Set("arn", nil) d.Set("ptr_record", nil) } d.Set("association_id", eip.AssociationId) diff --git a/internal/service/ec2/ec2_eip_data_source_test.go b/internal/service/ec2/ec2_eip_data_source_test.go index 40f8b6bdcdd..c9003a04c5e 100644 --- a/internal/service/ec2/ec2_eip_data_source_test.go +++ b/internal/service/ec2/ec2_eip_data_source_test.go @@ -27,6 +27,7 @@ func TestAccEC2EIPDataSource_filter(t *testing.T) { { Config: testAccEIPDataSourceConfig_filter(rName), Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"), resource.TestCheckResourceAttrPair(dataSourceName, "public_dns", resourceName, "public_dns"), resource.TestCheckResourceAttrPair(dataSourceName, "public_ip", resourceName, "public_ip"), diff --git a/internal/service/ec2/ec2_eip_test.go b/internal/service/ec2/ec2_eip_test.go index 12507de6854..5bdab0c6e6b 100644 --- a/internal/service/ec2/ec2_eip_test.go +++ b/internal/service/ec2/ec2_eip_test.go @@ -36,6 +36,7 @@ func TestAccEC2EIP_basic(t *testing.T) { Config: testAccEIPConfig_basic, Check: resource.ComposeTestCheckFunc( testAccCheckEIPExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttrSet(resourceName, "arn"), resource.TestCheckResourceAttr(resourceName, "domain", "vpc"), resource.TestCheckResourceAttr(resourceName, "ptr_record", ""), resource.TestCheckResourceAttrSet(resourceName, "public_ip"), From f180637c375d259f9e2ec4b33203d4b456593cd2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 10:27:36 -0400 Subject: [PATCH 17/35] Acceptance test output: % make testacc TESTARGS='-run=TestAccEC2EIPDataSource_filter\|TestAccEC2EIP_basic' PKG=ec2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go1.22.2 test ./internal/service/ec2/... -v -count 1 -parallel 20 -run=TestAccEC2EIPDataSource_filter\|TestAccEC2EIP_basic -timeout 360m === RUN TestAccEC2EIPDataSource_filter === PAUSE TestAccEC2EIPDataSource_filter === RUN TestAccEC2EIP_basic === PAUSE TestAccEC2EIP_basic === CONT TestAccEC2EIPDataSource_filter === CONT TestAccEC2EIP_basic --- PASS: TestAccEC2EIPDataSource_filter (18.78s) --- PASS: TestAccEC2EIP_basic (21.89s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 32.160s From 5d275e400cf752d8e60f6ce6c5e849ba3df52f7c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 10:45:48 -0400 Subject: [PATCH 18/35] r/aws_globalaccelerator_cross_account_attachment: Fixup acceptance tests. --- .../cross_account_attachment.go | 24 ++- .../cross_account_attachment_test.go | 194 +++++++++++++----- .../globalaccelerator/endpoint_group_test.go | 6 +- .../globalaccelerator/service_package_gen.go | 5 +- ...tor_cross_account_attachment.html.markdown | 13 +- 5 files changed, 171 insertions(+), 71 deletions(-) diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index 53cac2e989f..39cf5ee950d 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -23,6 +23,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/framework" fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" @@ -189,7 +190,7 @@ func (r *crossAccountAttachmentResource) Update(ctx context.Context, request res } if !new.Name.Equal(old.Name) { - input.Name = aws.String(new.Name.ValueString()) + input.Name = fwflex.StringFromFramework(ctx, new.Name) } if !new.Principals.Equal(old.Principals) { @@ -214,15 +215,18 @@ func (r *crossAccountAttachmentResource) Update(ctx context.Context, request res return v1.EndpointID.Equal(v2.EndpointID) && v1.Region.Equal(v2.Region) }) - response.Diagnostics.Append(fwflex.Expand(ctx, add, input.AddResources)...) - if response.Diagnostics.HasError() { - return - } - - response.Diagnostics.Append(fwflex.Expand(ctx, remove, input.RemoveResources)...) - if response.Diagnostics.HasError() { - return - } + input.AddResources = tfslices.ApplyToAll(add, func(v *resourceModel) *globalaccelerator.Resource { + return &globalaccelerator.Resource{ + EndpointId: fwflex.StringFromFramework(ctx, v.EndpointID), + Region: fwflex.StringFromFramework(ctx, v.Region), + } + }) + input.RemoveResources = tfslices.ApplyToAll(remove, func(v *resourceModel) *globalaccelerator.Resource { + return &globalaccelerator.Resource{ + EndpointId: fwflex.StringFromFramework(ctx, v.EndpointID), + Region: fwflex.StringFromFramework(ctx, v.Region), + } + }) } output, err := conn.UpdateCrossAccountAttachmentWithContext(ctx, input) diff --git a/internal/service/globalaccelerator/cross_account_attachment_test.go b/internal/service/globalaccelerator/cross_account_attachment_test.go index a4e175a423a..63840f72cf5 100644 --- a/internal/service/globalaccelerator/cross_account_attachment_test.go +++ b/internal/service/globalaccelerator/cross_account_attachment_test.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" tfglobalaccelerator "github.com/hashicorp/terraform-provider-aws/internal/service/globalaccelerator" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { @@ -26,10 +27,8 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { var v globalaccelerator.Attachment resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ @@ -65,25 +64,22 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_principals(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rAccountID1 := sdkacctest.RandStringFromCharSet(12, "012346789") + rAccountID2 := sdkacctest.RandStringFromCharSet(12, "012346789") var v globalaccelerator.Attachment - rAccountID := sdkacctest.RandStringFromCharSet(12, "012346789") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCrossAccountAttachmentConfig_principals(rName, rAccountID), + Config: testAccCrossAccountAttachmentConfig_principals(rName, rAccountID1), Check: resource.ComposeTestCheckFunc( testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), - resource.TestCheckResourceAttrSet(resourceName, "created_time"), - resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), - resource.TestCheckTypeSetElemAttr(resourceName, "principals.*", rAccountID), - resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "principals.#", "1"), + resource.TestCheckTypeSetElemAttr(resourceName, "principals.*", rAccountID1), ), }, { @@ -91,51 +87,50 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_principals(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccCrossAccountAttachmentConfig_principals(rName, rAccountID2), + Check: resource.ComposeTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "principals.#", "1"), + resource.TestCheckTypeSetElemAttr(resourceName, "principals.*", rAccountID2), + ), + }, }, }) } -/* func TestAccGlobalAcceleratorCrossAccountAttachment_resources(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - partition := acctest.Partition() - region := acctest.Region() - alternateRegion := acctest.AlternateRegion() - endpointID := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef0", partition, region) - endpointID2 := fmt.Sprintf("arn:%s:ec2:%s:171405876253:elastic-ip/eipalloc-1234567890abcdef1", partition, alternateRegion) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccCrossAccountAttachmentConfig_resources(rName, []tfglobalaccelerator.ResourceData{ - {EndpointID: types.StringValue(endpointID), Region: types.StringValue(region)}, - {EndpointID: types.StringValue(endpointID2), Region: types.StringValue(alternateRegion)}, - }), + Config: testAccCrossAccountAttachmentConfig_resources(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "resource.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccCrossAccountAttachmentConfig_resourcesUpdated(rName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ - "endpoint_id": endpointID, - "region": region, - }), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "resources.*", map[string]string{ - "endpoint_id": endpointID2, - "region": alternateRegion, - }), + resource.TestCheckResourceAttr(resourceName, "resource.#", "1"), ), }, }, }) } -*/ -// TODO: tags func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" @@ -143,10 +138,8 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { var v globalaccelerator.Attachment resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - }, - ErrorCheck: acctest.ErrorCheck(t, "aws_globalaccelerator_cross_account_attachment"), + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckCrossAccountAttachmentDestroy(ctx), Steps: []resource.TestStep{ @@ -162,6 +155,53 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { }) } +func TestAccGlobalAcceleratorCrossAccountAttachment_tags(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_globalaccelerator_cross_account_attachment.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + var v globalaccelerator.Attachment + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckAcceleratorDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCrossAccountAttachmentConfig_tags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccCrossAccountAttachmentConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccCrossAccountAttachmentConfig_tags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckCrossAccountAttachmentExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func testAccCheckCrossAccountAttachmentDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) @@ -181,7 +221,7 @@ func testAccCheckCrossAccountAttachmentDestroy(ctx context.Context) resource.Tes return err } - return fmt.Errorf("Global Accelerator ross-account Attachment %s still exists", rs.Primary.ID) + return fmt.Errorf("Global Accelerator Cross-account Attachment %s still exists", rs.Primary.ID) } return nil @@ -217,7 +257,7 @@ resource "aws_globalaccelerator_cross_account_attachment" "test" { `, rName) } -func testAccCrossAccountAttachmentConfig_principals(rName string, accountID string) string { +func testAccCrossAccountAttachmentConfig_principals(rName, accountID string) string { return fmt.Sprintf(` resource "aws_globalaccelerator_cross_account_attachment" "test" { name = %[1]q @@ -226,17 +266,63 @@ resource "aws_globalaccelerator_cross_account_attachment" "test" { `, rName, accountID) } -/* -func testAccCrossAccountAttachmentConfig_resources(rName string, resources []tfglobalaccelerator.ResourceData) string { - var resourcesStr []string - for _, r := range resources { - resourcesStr = append(resourcesStr, fmt.Sprintf(`{ endpoint_id = "%s", region = "%s" }`, r.EndpointID.ValueString(), r.Region.ValueString())) - } +func testAccCrossAccountAttachmentConfig_resources(rName string) string { + return acctest.ConfigCompose(testAccEndpointGroupConfig_baseALB(rName), fmt.Sprintf(` +resource "aws_eip" "test" { + tags = { + Name = %[1]q + } +} + +resource "aws_globalaccelerator_cross_account_attachment" "test" { + name = %[1]q + + resource { + endpoint_id = aws_lb.test.id + } +} +`, rName)) +} + +func testAccCrossAccountAttachmentConfig_resourcesUpdated(rName string) string { + return acctest.ConfigCompose(testAccEndpointGroupConfig_baseALB(rName), fmt.Sprintf(` +resource "aws_eip" "test" { + tags = { + Name = %[1]q + } +} + +resource "aws_globalaccelerator_cross_account_attachment" "test" { + name = %[1]q + + resource { + endpoint_id = aws_eip.test.arn + } +} +`, rName)) +} + +func testAccCrossAccountAttachmentConfig_tags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_globalaccelerator_cross_account_attachment" "test" { + name = %[1]q + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccCrossAccountAttachmentConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { return fmt.Sprintf(` resource "aws_globalaccelerator_cross_account_attachment" "test" { - name = "%s" - resources = [%s] + name = %[1]q + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } } -`, rName, strings.Join(resourcesStr, ", ")) +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) } -*/ diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index 3ba36305ae6..94a0d7e3f22 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -532,7 +532,7 @@ resource "aws_globalaccelerator_endpoint_group" "test" { `, rName) } -func testAccEndpointGroupConfig_albClientIP(rName string, clientIP bool, weight int) string { +func testAccEndpointGroupConfig_baseALB(rName string) string { return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 2), fmt.Sprintf(` resource "aws_lb" "test" { name = %[1]q @@ -578,7 +578,11 @@ resource "aws_internet_gateway" "test" { Name = %[1]q } } +`, rName)) +} +func testAccEndpointGroupConfig_albClientIP(rName string, clientIP bool, weight int) string { + return acctest.ConfigCompose(testAccEndpointGroupConfig_baseALB(rName), fmt.Sprintf(` resource "aws_globalaccelerator_accelerator" "test" { name = %[1]q ip_address_type = "IPV4" diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index 02ac07ab0f8..0c976a0672f 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -24,7 +24,10 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic return []*types.ServicePackageFrameworkResource{ { Factory: newCrossAccountAttachmentResource, - Name: "Cross Account Attachment", + Name: "Cross-account Attachment", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: "id", + }, }, } } diff --git a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown index bb7c718a92b..7a7edd54f8c 100644 --- a/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown +++ b/website/docs/r/globalaccelerator_cross_account_attachment.html.markdown @@ -26,10 +26,11 @@ resource "aws_globalaccelerator_cross_account_attachment" "example" { resource "aws_globalaccelerator_cross_account_attachment" "example" { name = "example-cross-account-attachment" principals = ["123456789012"] - resources = [ - { endpoint_id = "arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188", region = "us-west-2" }, - { endpoint_id = "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-other-load-balancer/50dc6c495c0c9189", region = "us-east-1" } - ] + + resource { + endpoint_id = "arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188" + region = "us-west-2" + } } ``` @@ -42,7 +43,9 @@ The following arguments are required: The following arguments are optional: * `principals` - (Optional) List of AWS account IDs that are allowed to associate resources with the accelerator. -* `resources` - (Optional) List of resources to be associated with the accelerator. Each resource is specified as a map with keys `endpoint_id` and `region`. The `region` field is optional. +* `resource` - (Optional) List of resources to be associated with the accelerator. + * `endpoint_id` - (Optional) The endpoint ID for the endpoint that is specified as a AWS resource. + * `region` - (Optional) The AWS Region where a shared endpoint resource is located. * `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ## Attribute Reference From 0b910997af554331bc83cdd4a133e4e845c1809d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 11:42:10 -0400 Subject: [PATCH 19/35] globalaccelerator: Use AWS SDK for Go v2. --- names/data/names_data.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/names/data/names_data.csv b/names/data/names_data.csv index a3efdbe3344..3ef7158d385 100644 --- a/names/data/names_data.csv +++ b/names/data/names_data.csv @@ -171,7 +171,7 @@ frauddetector,frauddetector,frauddetector,frauddetector,,frauddetector,,,FraudDe ,,,,,,,,,,,,,,,,,FreeRTOS,,x,,,,,,,,,No SDK support fsx,fsx,fsx,fsx,,fsx,,,FSx,FSx,,1,,,aws_fsx_,,fsx_,FSx,Amazon,,,,,,,FSx,DescribeFileSystems,, gamelift,gamelift,gamelift,gamelift,,gamelift,,,GameLift,GameLift,,1,,,aws_gamelift_,,gamelift_,GameLift,Amazon,,,,,,,GameLift,ListGameServerGroups,, -globalaccelerator,globalaccelerator,globalaccelerator,globalaccelerator,,globalaccelerator,,,GlobalAccelerator,GlobalAccelerator,x,1,,,aws_globalaccelerator_,,globalaccelerator_,Global Accelerator,AWS,,,,,,,Global Accelerator,ListAccelerators,, +globalaccelerator,globalaccelerator,globalaccelerator,globalaccelerator,,globalaccelerator,,,GlobalAccelerator,GlobalAccelerator,x,,2,,aws_globalaccelerator_,,globalaccelerator_,Global Accelerator,AWS,,,,,,,Global Accelerator,ListAccelerators,, glue,glue,glue,glue,,glue,,,Glue,Glue,,1,,,aws_glue_,,glue_,Glue,AWS,,,,,,,Glue,ListRegistries,, databrew,databrew,gluedatabrew,databrew,,databrew,,gluedatabrew,DataBrew,GlueDataBrew,,1,,,aws_databrew_,,databrew_,Glue DataBrew,AWS,,x,,,,,DataBrew,,, groundstation,groundstation,groundstation,groundstation,,groundstation,,,GroundStation,GroundStation,,,2,,aws_groundstation_,,groundstation_,Ground Station,AWS,,,,,,,GroundStation,ListConfigs,, From 172661d416b098f9642f0c3a7a1fe28ae7d66399 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 11:43:38 -0400 Subject: [PATCH 20/35] globalaccelerator: AWS SDK for Go v2 tagging codewq. --- internal/service/globalaccelerator/generate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/globalaccelerator/generate.go b/internal/service/globalaccelerator/generate.go index e3f90ea20bd..77472c95ab3 100644 --- a/internal/service/globalaccelerator/generate.go +++ b/internal/service/globalaccelerator/generate.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/tags/main.go -ListTags -ServiceTagsSlice -UpdateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTags -ServiceTagsSlice -UpdateTags //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. From b52e88904c7ffdbd82dbcf7a30bce263b54231f3 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 11:44:31 -0400 Subject: [PATCH 21/35] Run 'make gen'. --- internal/conns/awsclient_gen.go | 6 +-- .../service_endpoints_gen_test.go | 40 +++++++++++-------- .../service/globalaccelerator/tags_gen.go | 36 ++++++++--------- 3 files changed, 45 insertions(+), 37 deletions(-) diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index ad4fe435f1b..b67f6a932f3 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -81,6 +81,7 @@ import ( fis_sdkv2 "github.com/aws/aws-sdk-go-v2/service/fis" fms_sdkv2 "github.com/aws/aws-sdk-go-v2/service/fms" glacier_sdkv2 "github.com/aws/aws-sdk-go-v2/service/glacier" + globalaccelerator_sdkv2 "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" groundstation_sdkv2 "github.com/aws/aws-sdk-go-v2/service/groundstation" healthlake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/healthlake" iam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/iam" @@ -195,7 +196,6 @@ import ( emrcontainers_sdkv1 "github.com/aws/aws-sdk-go/service/emrcontainers" fsx_sdkv1 "github.com/aws/aws-sdk-go/service/fsx" gamelift_sdkv1 "github.com/aws/aws-sdk-go/service/gamelift" - globalaccelerator_sdkv1 "github.com/aws/aws-sdk-go/service/globalaccelerator" glue_sdkv1 "github.com/aws/aws-sdk-go/service/glue" greengrass_sdkv1 "github.com/aws/aws-sdk-go/service/greengrass" guardduty_sdkv1 "github.com/aws/aws-sdk-go/service/guardduty" @@ -698,8 +698,8 @@ func (c *AWSClient) GlacierClient(ctx context.Context) *glacier_sdkv2.Client { return errs.Must(client[*glacier_sdkv2.Client](ctx, c, names.Glacier, make(map[string]any))) } -func (c *AWSClient) GlobalAcceleratorConn(ctx context.Context) *globalaccelerator_sdkv1.GlobalAccelerator { - return errs.Must(conn[*globalaccelerator_sdkv1.GlobalAccelerator](ctx, c, names.GlobalAccelerator, make(map[string]any))) +func (c *AWSClient) GlobalAcceleratorClient(ctx context.Context) *globalaccelerator_sdkv2.Client { + return errs.Must(client[*globalaccelerator_sdkv2.Client](ctx, c, names.GlobalAccelerator, make(map[string]any))) } func (c *AWSClient) GlueConn(ctx context.Context) *glue_sdkv1.Glue { diff --git a/internal/service/globalaccelerator/service_endpoints_gen_test.go b/internal/service/globalaccelerator/service_endpoints_gen_test.go index beddae7df67..0d337e6ad70 100644 --- a/internal/service/globalaccelerator/service_endpoints_gen_test.go +++ b/internal/service/globalaccelerator/service_endpoints_gen_test.go @@ -4,17 +4,17 @@ package globalaccelerator_test import ( "context" + "errors" "fmt" "maps" - "net/url" "os" "path/filepath" "reflect" "strings" "testing" - "github.com/aws/aws-sdk-go/aws/endpoints" - globalaccelerator_sdkv1 "github.com/aws/aws-sdk-go/service/globalaccelerator" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + globalaccelerator_sdkv2 "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" "github.com/google/go-cmp/cmp" @@ -212,34 +212,42 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } func defaultEndpoint(region string) string { - r := endpoints.DefaultResolver() + r := globalaccelerator_sdkv2.NewDefaultEndpointResolverV2() - ep, err := r.EndpointFor(globalaccelerator_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { - opt.ResolveUnknownService = true + ep, err := r.ResolveEndpoint(context.Background(), globalaccelerator_sdkv2.EndpointParameters{ + Region: aws_sdkv2.String(region), }) if err != nil { return err.Error() } - url, _ := url.Parse(ep.URL) - - if url.Path == "" { - url.Path = "/" + if ep.URI.Path == "" { + ep.URI.Path = "/" } - return url.String() + return ep.URI.String() } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) string { t.Helper() - client := meta.GlobalAcceleratorConn(ctx) - - req, _ := client.ListAcceleratorsRequest(&globalaccelerator_sdkv1.ListAcceleratorsInput{}) + var endpoint string - req.HTTPRequest.URL.Path = "/" + client := meta.GlobalAcceleratorClient(ctx) - endpoint := req.HTTPRequest.URL.String() + _, err := client.ListAccelerators(ctx, &globalaccelerator_sdkv2.ListAcceleratorsInput{}, + func(opts *globalaccelerator_sdkv2.Options) { + opts.APIOptions = append(opts.APIOptions, + addRetrieveEndpointURLMiddleware(t, &endpoint), + addCancelRequestMiddleware(), + ) + }, + ) + if err == nil { + t.Fatal("Expected an error, got none") + } else if !errors.Is(err, errCancelOperation) { + t.Fatalf("Unexpected error: %s", err) + } return endpoint } diff --git a/internal/service/globalaccelerator/tags_gen.go b/internal/service/globalaccelerator/tags_gen.go index e9974334e9e..49aeeefe362 100644 --- a/internal/service/globalaccelerator/tags_gen.go +++ b/internal/service/globalaccelerator/tags_gen.go @@ -5,9 +5,9 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "github.com/aws/aws-sdk-go/service/globalaccelerator/globalacceleratoriface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/logging" @@ -19,12 +19,12 @@ import ( // listTags lists globalaccelerator service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func listTags(ctx context.Context, conn globalacceleratoriface.GlobalAcceleratorAPI, identifier string) (tftags.KeyValueTags, error) { +func listTags(ctx context.Context, conn *globalaccelerator.Client, identifier string, optFns ...func(*globalaccelerator.Options)) (tftags.KeyValueTags, error) { input := &globalaccelerator.ListTagsForResourceInput{ ResourceArn: aws.String(identifier), } - output, err := conn.ListTagsForResourceWithContext(ctx, input) + output, err := conn.ListTagsForResource(ctx, input, optFns...) if err != nil { return tftags.New(ctx, nil), err @@ -36,7 +36,7 @@ func listTags(ctx context.Context, conn globalacceleratoriface.GlobalAccelerator // ListTags lists globalaccelerator service tags and set them in Context. // It is called from outside this package. func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { - tags, err := listTags(ctx, meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx), identifier) + tags, err := listTags(ctx, meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx), identifier) if err != nil { return err @@ -52,11 +52,11 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier stri // []*SERVICE.Tag handling // Tags returns globalaccelerator service tags. -func Tags(tags tftags.KeyValueTags) []*globalaccelerator.Tag { - result := make([]*globalaccelerator.Tag, 0, len(tags)) +func Tags(tags tftags.KeyValueTags) []awstypes.Tag { + result := make([]awstypes.Tag, 0, len(tags)) for k, v := range tags.Map() { - tag := &globalaccelerator.Tag{ + tag := awstypes.Tag{ Key: aws.String(k), Value: aws.String(v), } @@ -68,11 +68,11 @@ func Tags(tags tftags.KeyValueTags) []*globalaccelerator.Tag { } // KeyValueTags creates tftags.KeyValueTags from globalaccelerator service tags. -func KeyValueTags(ctx context.Context, tags []*globalaccelerator.Tag) tftags.KeyValueTags { +func KeyValueTags(ctx context.Context, tags []awstypes.Tag) tftags.KeyValueTags { m := make(map[string]*string, len(tags)) for _, tag := range tags { - m[aws.StringValue(tag.Key)] = tag.Value + m[aws.ToString(tag.Key)] = tag.Value } return tftags.New(ctx, m) @@ -80,7 +80,7 @@ func KeyValueTags(ctx context.Context, tags []*globalaccelerator.Tag) tftags.Key // getTagsIn returns globalaccelerator service tags from Context. // nil is returned if there are no input tags. -func getTagsIn(ctx context.Context) []*globalaccelerator.Tag { +func getTagsIn(ctx context.Context) []awstypes.Tag { if inContext, ok := tftags.FromContext(ctx); ok { if tags := Tags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { return tags @@ -91,7 +91,7 @@ func getTagsIn(ctx context.Context) []*globalaccelerator.Tag { } // setTagsOut sets globalaccelerator service tags in Context. -func setTagsOut(ctx context.Context, tags []*globalaccelerator.Tag) { +func setTagsOut(ctx context.Context, tags []awstypes.Tag) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = option.Some(KeyValueTags(ctx, tags)) } @@ -100,7 +100,7 @@ func setTagsOut(ctx context.Context, tags []*globalaccelerator.Tag) { // updateTags updates globalaccelerator service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func updateTags(ctx context.Context, conn globalacceleratoriface.GlobalAcceleratorAPI, identifier string, oldTagsMap, newTagsMap any) error { +func updateTags(ctx context.Context, conn *globalaccelerator.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*globalaccelerator.Options)) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -111,10 +111,10 @@ func updateTags(ctx context.Context, conn globalacceleratoriface.GlobalAccelerat if len(removedTags) > 0 { input := &globalaccelerator.UntagResourceInput{ ResourceArn: aws.String(identifier), - TagKeys: aws.StringSlice(removedTags.Keys()), + TagKeys: removedTags.Keys(), } - _, err := conn.UntagResourceWithContext(ctx, input) + _, err := conn.UntagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("untagging resource (%s): %w", identifier, err) @@ -129,7 +129,7 @@ func updateTags(ctx context.Context, conn globalacceleratoriface.GlobalAccelerat Tags: Tags(updatedTags), } - _, err := conn.TagResourceWithContext(ctx, input) + _, err := conn.TagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("tagging resource (%s): %w", identifier, err) @@ -142,5 +142,5 @@ func updateTags(ctx context.Context, conn globalacceleratoriface.GlobalAccelerat // UpdateTags updates globalaccelerator service tags. // It is called from outside this package. func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { - return updateTags(ctx, meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx), identifier, oldTags, newTags) + return updateTags(ctx, meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx), identifier, oldTags, newTags) } From 4889af33e5df538fb7ef3b4f877231770c25cdd4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 11:46:25 -0400 Subject: [PATCH 22/35] Run 'go get github.com/aws/aws-sdk-go-v2/service/globalaccelerator@v1.23.1 && go mod tidy'. --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index c28905da16a..98d1c47a611 100644 --- a/go.mod +++ b/go.mod @@ -89,6 +89,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/fis v1.24.2 github.com/aws/aws-sdk-go-v2/service/fms v1.31.4 github.com/aws/aws-sdk-go-v2/service/glacier v1.22.4 + github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.23.1 github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.0 github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.0 github.com/aws/aws-sdk-go-v2/service/iam v1.32.0 diff --git a/go.sum b/go.sum index 7094bb13a27..7e43fbff103 100644 --- a/go.sum +++ b/go.sum @@ -198,6 +198,8 @@ github.com/aws/aws-sdk-go-v2/service/fms v1.31.4 h1:gY+Dp2QdphY6m5IVkETmsNauYztd github.com/aws/aws-sdk-go-v2/service/fms v1.31.4/go.mod h1:X4DjA4sm8cobhR9DtHn947+dLYxU1oWq3zwRZUmFSLo= github.com/aws/aws-sdk-go-v2/service/glacier v1.22.4 h1:y0/RN8LwIbyDTPe/dnDBdsCw89ko8ZNFPW4vStye4aE= github.com/aws/aws-sdk-go-v2/service/glacier v1.22.4/go.mod h1:8ofkOuh1SZLKR5EdfxPhQ1UgaQuCBAZzUwbeIBmeKIM= +github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.23.1 h1:E48tPAIKptyIb8OFOAsZ3xSzjwou8A63f40ao1H3tVU= +github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.23.1/go.mod h1:6morRSCgJD400qAu5DCEtvoaAC1owS5t6oq8ddLLwxw= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.0 h1:joAdQdtfg8Yy/e5Pq5qwAe0hjH3+EJUzd1jPrlXE3SA= github.com/aws/aws-sdk-go-v2/service/groundstation v1.27.0/go.mod h1:yGNTqdu48YxjsCyLpalmwHCQF52GGERK7+J3nTcvJ3A= github.com/aws/aws-sdk-go-v2/service/healthlake v1.24.0 h1:HRcwttYPNlE5mv6uDlcsk9m4oV3fxV8+a+V4U3jIMd4= From 2b33949a61ba9d76198545d0051255812bee2d36 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 12:01:15 -0400 Subject: [PATCH 23/35] r/aws_globalaccelerator_accelerator: Migrate to AWS SDK for GO v2. --- .../service/globalaccelerator/accelerator.go | 126 +++++++++--------- .../globalaccelerator/accelerator_test.go | 45 +++---- .../service/globalaccelerator/exports_test.go | 2 + .../globalaccelerator/service_package_gen.go | 2 +- 4 files changed, 85 insertions(+), 90 deletions(-) diff --git a/internal/service/globalaccelerator/accelerator.go b/internal/service/globalaccelerator/accelerator.go index fda5db63211..5125deaa3bc 100644 --- a/internal/service/globalaccelerator/accelerator.go +++ b/internal/service/globalaccelerator/accelerator.go @@ -9,15 +9,17 @@ import ( "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "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/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/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" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -28,7 +30,7 @@ import ( // @SDKResource("aws_globalaccelerator_accelerator", name="Accelerator") // @Tags(identifierAttribute="id") -func ResourceAccelerator() *schema.Resource { +func resourceAccelerator() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceAcceleratorCreate, ReadWithoutTimeout: resourceAcceleratorRead, @@ -88,10 +90,10 @@ func ResourceAccelerator() *schema.Resource { Computed: true, }, "ip_address_type": { - Type: schema.TypeString, - Optional: true, - Default: globalaccelerator.IpAddressTypeIpv4, - ValidateFunc: validation.StringInSlice(globalaccelerator.IpAddressType_Values(), false), + Type: schema.TypeString, + Optional: true, + Default: awstypes.IpAddressTypeIpv4, + ValidateDiagFunc: enum.Validate[awstypes.IpAddressType](), }, "ip_addresses": { Type: schema.TypeList, @@ -136,8 +138,7 @@ func ResourceAccelerator() *schema.Resource { func resourceAcceleratorCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) name := d.Get("name").(string) input := &globalaccelerator.CreateAcceleratorInput{ @@ -148,37 +149,37 @@ func resourceAcceleratorCreate(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("ip_address_type"); ok { - input.IpAddressType = aws.String(v.(string)) + input.IpAddressType = awstypes.IpAddressType(v.(string)) } if v, ok := d.GetOk("ip_addresses"); ok && len(v.([]interface{})) > 0 { - input.IpAddresses = flex.ExpandStringList(v.([]interface{})) + input.IpAddresses = flex.ExpandStringValueList(v.([]interface{})) } - output, err := conn.CreateAcceleratorWithContext(ctx, input) + output, err := conn.CreateAccelerator(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Global Accelerator Accelerator (%s): %s", name, err) } - d.SetId(aws.StringValue(output.Accelerator.AcceleratorArn)) + d.SetId(aws.ToString(output.Accelerator.AcceleratorArn)) if _, err := waitAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", d.Id(), err) } if v, ok := d.GetOk("attributes"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { input := expandUpdateAcceleratorAttributesInput(v.([]interface{})[0].(map[string]interface{})) input.AcceleratorArn = aws.String(d.Id()) - _, err := conn.UpdateAcceleratorAttributesWithContext(ctx, input) + _, err := conn.UpdateAcceleratorAttributes(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Accelerator (%s) attributes: %s", d.Id(), err) } if _, err := waitAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", d.Id(), err) } } @@ -187,10 +188,9 @@ func resourceAcceleratorCreate(ctx context.Context, d *schema.ResourceData, meta func resourceAcceleratorRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) - - accelerator, err := FindAcceleratorByARN(ctx, conn, d.Id()) + accelerator, err := findAcceleratorByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Global Accelerator Accelerator (%s) not found, removing from state", d.Id()) @@ -212,7 +212,7 @@ func resourceAcceleratorRead(ctx context.Context, d *schema.ResourceData, meta i } d.Set("name", accelerator.Name) - acceleratorAttributes, err := FindAcceleratorAttributesByARN(ctx, conn, d.Id()) + acceleratorAttributes, err := findAcceleratorAttributesByARN(ctx, conn, d.Id()) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Accelerator (%s) attributes: %s", d.Id(), err) @@ -227,8 +227,7 @@ func resourceAcceleratorRead(ctx context.Context, d *schema.ResourceData, meta i func resourceAcceleratorUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) if d.HasChanges("name", "ip_address_type", "enabled") { input := &globalaccelerator.UpdateAcceleratorInput{ @@ -238,17 +237,17 @@ func resourceAcceleratorUpdate(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("ip_address_type"); ok { - input.IpAddressType = aws.String(v.(string)) + input.IpAddressType = awstypes.IpAddressType(v.(string)) } - _, err := conn.UpdateAcceleratorWithContext(ctx, input) + _, err := conn.UpdateAccelerator(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Accelerator (%s): %s", d.Id(), err) } if _, err := waitAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", d.Id(), err) } } @@ -262,28 +261,28 @@ func resourceAcceleratorUpdate(ctx context.Context, d *schema.ResourceData, meta nInput.AcceleratorArn = aws.String(d.Id()) // To change flow logs bucket and prefix attributes while flows are enabled, first disable flow logs. - if aws.BoolValue(oInput.FlowLogsEnabled) && aws.BoolValue(nInput.FlowLogsEnabled) { + if aws.ToBool(oInput.FlowLogsEnabled) && aws.ToBool(nInput.FlowLogsEnabled) { oInput.FlowLogsEnabled = aws.Bool(false) - _, err := conn.UpdateAcceleratorAttributesWithContext(ctx, oInput) + _, err := conn.UpdateAcceleratorAttributes(ctx, oInput) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Accelerator (%s) attributes: %s", d.Id(), err) } if _, err := waitAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", d.Id(), err) } } - _, err := conn.UpdateAcceleratorAttributesWithContext(ctx, nInput) + _, err := conn.UpdateAcceleratorAttributes(ctx, nInput) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Accelerator (%s) attributes: %s", d.Id(), err) } if _, err := waitAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", d.Id(), err) } } } @@ -294,17 +293,16 @@ func resourceAcceleratorUpdate(ctx context.Context, d *schema.ResourceData, meta func resourceAcceleratorDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) input := &globalaccelerator.UpdateAcceleratorInput{ AcceleratorArn: aws.String(d.Id()), Enabled: aws.Bool(false), } - _, err := conn.UpdateAcceleratorWithContext(ctx, input) + _, err := conn.UpdateAccelerator(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return diags } @@ -313,15 +311,15 @@ func resourceAcceleratorDelete(ctx context.Context, d *schema.ResourceData, meta } if _, err := waitAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", d.Id(), err) } log.Printf("[DEBUG] Deleting Global Accelerator Accelerator: %s", d.Id()) - _, err = conn.DeleteAcceleratorWithContext(ctx, &globalaccelerator.DeleteAcceleratorInput{ + _, err = conn.DeleteAccelerator(ctx, &globalaccelerator.DeleteAcceleratorInput{ AcceleratorArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return diags } @@ -332,7 +330,7 @@ func resourceAcceleratorDelete(ctx context.Context, d *schema.ResourceData, meta return diags } -func FindAcceleratorByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.Accelerator, error) { +func findAcceleratorByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.Accelerator, error) { input := &globalaccelerator.DescribeAcceleratorInput{ AcceleratorArn: aws.String(arn), } @@ -340,10 +338,10 @@ func FindAcceleratorByARN(ctx context.Context, conn *globalaccelerator.GlobalAcc return findAccelerator(ctx, conn, input) } -func findAccelerator(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeAcceleratorInput) (*globalaccelerator.Accelerator, error) { - output, err := conn.DescribeAcceleratorWithContext(ctx, input) +func findAccelerator(ctx context.Context, conn *globalaccelerator.Client, input *globalaccelerator.DescribeAcceleratorInput) (*awstypes.Accelerator, error) { + output, err := conn.DescribeAccelerator(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -361,7 +359,7 @@ func findAccelerator(ctx context.Context, conn *globalaccelerator.GlobalAccelera return output.Accelerator, nil } -func FindAcceleratorAttributesByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.AcceleratorAttributes, error) { +func findAcceleratorAttributesByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.AcceleratorAttributes, error) { input := &globalaccelerator.DescribeAcceleratorAttributesInput{ AcceleratorArn: aws.String(arn), } @@ -369,10 +367,10 @@ func FindAcceleratorAttributesByARN(ctx context.Context, conn *globalaccelerator return findAcceleratorAttributes(ctx, conn, input) } -func findAcceleratorAttributes(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeAcceleratorAttributesInput) (*globalaccelerator.AcceleratorAttributes, error) { - output, err := conn.DescribeAcceleratorAttributesWithContext(ctx, input) +func findAcceleratorAttributes(ctx context.Context, conn *globalaccelerator.Client, input *globalaccelerator.DescribeAcceleratorAttributesInput) (*awstypes.AcceleratorAttributes, error) { + output, err := conn.DescribeAcceleratorAttributes(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -390,9 +388,9 @@ func findAcceleratorAttributes(ctx context.Context, conn *globalaccelerator.Glob return output.AcceleratorAttributes, nil } -func statusAccelerator(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) retry.StateRefreshFunc { +func statusAccelerator(ctx context.Context, conn *globalaccelerator.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - accelerator, err := FindAcceleratorByARN(ctx, conn, arn) + accelerator, err := findAcceleratorByARN(ctx, conn, arn) if tfresource.NotFound(err) { return nil, "", nil @@ -402,21 +400,21 @@ func statusAccelerator(ctx context.Context, conn *globalaccelerator.GlobalAccele return nil, "", err } - return accelerator, aws.StringValue(accelerator.Status), nil + return accelerator, string(accelerator.Status), nil } } -func waitAcceleratorDeployed(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string, timeout time.Duration) (*globalaccelerator.Accelerator, error) { //nolint:unparam +func waitAcceleratorDeployed(ctx context.Context, conn *globalaccelerator.Client, arn string, timeout time.Duration) (*awstypes.Accelerator, error) { //nolint:unparam stateConf := &retry.StateChangeConf{ - Pending: []string{globalaccelerator.AcceleratorStatusInProgress}, - Target: []string{globalaccelerator.AcceleratorStatusDeployed}, + Pending: enum.Slice(awstypes.AcceleratorStatusInProgress), + Target: enum.Slice(awstypes.AcceleratorStatusDeployed), Refresh: statusAccelerator(ctx, conn, arn), Timeout: timeout, } outputRaw, err := stateConf.WaitForStateContext(ctx) - if output, ok := outputRaw.(*globalaccelerator.Accelerator); ok { + if output, ok := outputRaw.(*awstypes.Accelerator); ok { return output, err } @@ -445,7 +443,7 @@ func expandUpdateAcceleratorAttributesInput(tfMap map[string]interface{}) *globa return apiObject } -func flattenIPSet(apiObject *globalaccelerator.IpSet) map[string]interface{} { +func flattenIPSet(apiObject *awstypes.IpSet) map[string]interface{} { if apiObject == nil { return nil } @@ -453,17 +451,17 @@ func flattenIPSet(apiObject *globalaccelerator.IpSet) map[string]interface{} { tfMap := map[string]interface{}{} if v := apiObject.IpAddresses; v != nil { - tfMap["ip_addresses"] = aws.StringValueSlice(v) + tfMap["ip_addresses"] = v } if v := apiObject.IpFamily; v != nil { - tfMap["ip_family"] = aws.StringValue(v) + tfMap["ip_family"] = aws.ToString(v) } return tfMap } -func flattenIPSets(apiObjects []*globalaccelerator.IpSet) []interface{} { +func flattenIPSets(apiObjects []awstypes.IpSet) []interface{} { if len(apiObjects) == 0 { return nil } @@ -471,17 +469,13 @@ func flattenIPSets(apiObjects []*globalaccelerator.IpSet) []interface{} { var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenIPSet(apiObject)) + tfList = append(tfList, flattenIPSet(&apiObject)) } return tfList } -func flattenAcceleratorAttributes(apiObject *globalaccelerator.AcceleratorAttributes) map[string]interface{} { +func flattenAcceleratorAttributes(apiObject *awstypes.AcceleratorAttributes) map[string]interface{} { if apiObject == nil { return nil } @@ -489,15 +483,15 @@ func flattenAcceleratorAttributes(apiObject *globalaccelerator.AcceleratorAttrib tfMap := map[string]interface{}{} if v := apiObject.FlowLogsEnabled; v != nil { - tfMap["flow_logs_enabled"] = aws.BoolValue(v) + tfMap["flow_logs_enabled"] = aws.ToBool(v) } if v := apiObject.FlowLogsS3Bucket; v != nil { - tfMap["flow_logs_s3_bucket"] = aws.StringValue(v) + tfMap["flow_logs_s3_bucket"] = aws.ToString(v) } if v := apiObject.FlowLogsS3Prefix; v != nil { - tfMap["flow_logs_s3_prefix"] = aws.StringValue(v) + tfMap["flow_logs_s3_prefix"] = aws.ToString(v) } return tfMap diff --git a/internal/service/globalaccelerator/accelerator_test.go b/internal/service/globalaccelerator/accelerator_test.go index 30e73e9554c..53e7aceb61f 100644 --- a/internal/service/globalaccelerator/accelerator_test.go +++ b/internal/service/globalaccelerator/accelerator_test.go @@ -11,7 +11,9 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/globalaccelerator" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -331,11 +333,11 @@ func TestAccGlobalAcceleratorAccelerator_tags(t *testing.T) { } func testAccPreCheck(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListAcceleratorsInput{} - _, err := conn.ListAcceleratorsWithContext(ctx, input) + _, err := conn.ListAccelerators(ctx, input) if acctest.PreCheckSkipError(err) { t.Skipf("skipping acceptance testing: %s", err) @@ -355,19 +357,24 @@ func testAccCheckBYOIPExists(ctx context.Context, t *testing.T) { parsedAddr := net.ParseIP(requestedAddr) - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListByoipCidrsInput{} - cidrs := make([]*globalaccelerator.ByoipCidr, 0) + cidrs := make([]awstypes.ByoipCidr, 0) - err := conn.ListByoipCidrsPagesWithContext(ctx, input, - func(page *globalaccelerator.ListByoipCidrsOutput, lastPage bool) bool { - cidrs = append(cidrs, page.ByoipCidrs...) - return !lastPage - }) + pages := globalaccelerator.NewListByoipCidrsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) - if acctest.PreCheckSkipError(err) { - t.Skipf("skipping acceptance testing: %s", err) + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } + + cidrs = append(cidrs, page.ByoipCidrs...) } if len(cidrs) == 0 { @@ -377,7 +384,7 @@ func testAccCheckBYOIPExists(ctx context.Context, t *testing.T) { matches := false for _, cidr := range cidrs { - _, network, _ := net.ParseCIDR(*cidr.Cidr) + _, network, _ := net.ParseCIDR(aws.ToString(cidr.Cidr)) if network.Contains(parsedAddr) { matches = true break @@ -387,24 +394,16 @@ func testAccCheckBYOIPExists(ctx context.Context, t *testing.T) { if !matches { t.Skipf("skipping acceptance testing: requested address %s not available via BYOIP", requestedAddr) } - - if err != nil { - t.Fatalf("unexpected PreCheck error: %s", err) - } } func testAccCheckAcceleratorExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Global Accelerator Accelerator ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) _, err := tfglobalaccelerator.FindAcceleratorByARN(ctx, conn, rs.Primary.ID) @@ -414,7 +413,7 @@ func testAccCheckAcceleratorExists(ctx context.Context, n string) resource.TestC func testAccCheckAcceleratorDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_globalaccelerator_accelerator" { diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index 4d8047be515..d341722a046 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -5,7 +5,9 @@ package globalaccelerator // Exports for use in tests only. var ( + ResourceAccelerator = resourceAccelerator ResourceCrossAccountAttachment = newCrossAccountAttachmentResource + FindAcceleratorByARN = findAcceleratorByARN FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN ) diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index 0c976a0672f..ce15945e679 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -44,7 +44,7 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ { - Factory: ResourceAccelerator, + Factory: resourceAccelerator, TypeName: "aws_globalaccelerator_accelerator", Name: "Accelerator", Tags: &types.ServicePackageResourceTags{ From d91a0c471b6856b57bc0ef8d598f3675bee7aa35 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 12:36:57 -0400 Subject: [PATCH 24/35] d/aws_globalaccelerator_accelerator: Migrate to AWS SDK for GO v2. --- .../service/globalaccelerator/accelerator.go | 8 -- .../accelerator_data_source.go | 96 ++++++++----------- .../globalaccelerator/service_package_gen.go | 3 +- 3 files changed, 42 insertions(+), 65 deletions(-) diff --git a/internal/service/globalaccelerator/accelerator.go b/internal/service/globalaccelerator/accelerator.go index 5125deaa3bc..0ac9acc97f3 100644 --- a/internal/service/globalaccelerator/accelerator.go +++ b/internal/service/globalaccelerator/accelerator.go @@ -335,10 +335,6 @@ func findAcceleratorByARN(ctx context.Context, conn *globalaccelerator.Client, a AcceleratorArn: aws.String(arn), } - return findAccelerator(ctx, conn, input) -} - -func findAccelerator(ctx context.Context, conn *globalaccelerator.Client, input *globalaccelerator.DescribeAcceleratorInput) (*awstypes.Accelerator, error) { output, err := conn.DescribeAccelerator(ctx, input) if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { @@ -364,10 +360,6 @@ func findAcceleratorAttributesByARN(ctx context.Context, conn *globalaccelerator AcceleratorArn: aws.String(arn), } - return findAcceleratorAttributes(ctx, conn, input) -} - -func findAcceleratorAttributes(ctx context.Context, conn *globalaccelerator.Client, input *globalaccelerator.DescribeAcceleratorAttributesInput) (*awstypes.AcceleratorAttributes, error) { output, err := conn.DescribeAcceleratorAttributes(ctx, input) if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { diff --git a/internal/service/globalaccelerator/accelerator_data_source.go b/internal/service/globalaccelerator/accelerator_data_source.go index 043cf82226d..bff370d14c3 100644 --- a/internal/service/globalaccelerator/accelerator_data_source.go +++ b/internal/service/globalaccelerator/accelerator_data_source.go @@ -6,8 +6,9 @@ package globalaccelerator import ( "context" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -16,35 +17,34 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/names" ) -// @FrameworkDataSource -func newDataSourceAccelerator(context.Context) (datasource.DataSourceWithConfigure, error) { - d := &dataSourceAccelerator{} +// @FrameworkDataSource(name="Accelerator") +func newAcceleratorDataSource(context.Context) (datasource.DataSourceWithConfigure, error) { + d := &acceleratorDataSource{} return d, nil } -type dataSourceAccelerator struct { +type acceleratorDataSource struct { framework.DataSourceWithConfigure } -// Metadata should return the full name of the data source, such as -// examplecloud_thing. -func (d *dataSourceAccelerator) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { +func (*acceleratorDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) { response.TypeName = "aws_globalaccelerator_accelerator" } -// Schema returns the schema for this data source. -func (d *dataSourceAccelerator) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (d *acceleratorDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ - "arn": schema.StringAttribute{ + names.AttrARN: schema.StringAttribute{ CustomType: fwtypes.ARNType, Optional: true, Computed: true, }, "attributes": schema.ListAttribute{ + Computed: true, ElementType: types.ObjectType{ AttrTypes: map[string]attr.Type{ "flow_logs_enabled": types.BoolType, @@ -52,7 +52,6 @@ func (d *dataSourceAccelerator) Schema(ctx context.Context, req datasource.Schem "flow_logs_s3_prefix": types.StringType, }, }, - Computed: true, }, "dns_name": schema.StringAttribute{ Computed: true, @@ -66,7 +65,7 @@ func (d *dataSourceAccelerator) Schema(ctx context.Context, req datasource.Schem "hosted_zone_id": schema.StringAttribute{ Computed: true, }, - "id": schema.StringAttribute{ + names.AttrID: schema.StringAttribute{ Optional: true, Computed: true, }, @@ -74,13 +73,13 @@ func (d *dataSourceAccelerator) Schema(ctx context.Context, req datasource.Schem Computed: true, }, "ip_sets": schema.ListAttribute{ + Computed: true, ElementType: types.ObjectType{ AttrTypes: map[string]attr.Type{ "ip_addresses": types.ListType{ElemType: types.StringType}, "ip_family": types.StringType, }, }, - Computed: true, }, "name": schema.StringAttribute{ Optional: true, @@ -91,49 +90,38 @@ func (d *dataSourceAccelerator) Schema(ctx context.Context, req datasource.Schem } } -// Read is called when the provider must read data source values in order to update state. -// Config values should be read from the ReadRequest and new state values set on the ReadResponse. -func (d *dataSourceAccelerator) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var data dataSourceAcceleratorData - +func (d *acceleratorDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var data acceleratorDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) - if response.Diagnostics.HasError() { return } - conn := d.Meta().GlobalAcceleratorConn(ctx) + conn := d.Meta().GlobalAcceleratorClient(ctx) ignoreTagsConfig := d.Meta().IgnoreTagsConfig - var results []*globalaccelerator.Accelerator - err := conn.ListAcceleratorsPagesWithContext(ctx, &globalaccelerator.ListAcceleratorsInput{}, func(page *globalaccelerator.ListAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage - } + var results []awstypes.Accelerator + pages := globalaccelerator.NewListAcceleratorsPaginator(conn, &globalaccelerator.ListAcceleratorsInput{}) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) - for _, accelerator := range page.Accelerators { - if accelerator == nil { - continue - } + if err != nil { + response.Diagnostics.AddError("listing Global Accelerator Accelerators", err.Error()) - if !data.ARN.IsNull() && data.ARN.ValueString() != aws.StringValue(accelerator.AcceleratorArn) { + return + } + + for _, v := range page.Accelerators { + if !data.ARN.IsNull() && data.ARN.ValueString() != aws.ToString(v.AcceleratorArn) { continue } - if !data.Name.IsNull() && data.Name.ValueString() != aws.StringValue(accelerator.Name) { + if !data.Name.IsNull() && data.Name.ValueString() != aws.ToString(v.Name) { continue } - results = append(results, accelerator) + results = append(results, v) } - - return !lastPage - }) - - if err != nil { - response.Diagnostics.AddError("listing Global Accelerator Accelerators", err.Error()) - - return } if n := len(results); n == 0 { @@ -147,18 +135,18 @@ func (d *dataSourceAccelerator) Read(ctx context.Context, request datasource.Rea } accelerator := results[0] - acceleratorARN := aws.StringValue(accelerator.AcceleratorArn) + acceleratorARN := aws.ToString(accelerator.AcceleratorArn) data.ARN = flex.StringToFrameworkARN(ctx, accelerator.AcceleratorArn) data.DnsName = flex.StringToFrameworkLegacy(ctx, accelerator.DnsName) data.DualStackDNSName = flex.StringToFrameworkLegacy(ctx, accelerator.DualStackDnsName) data.Enabled = flex.BoolToFrameworkLegacy(ctx, accelerator.Enabled) data.HostedZoneID = types.StringValue(d.Meta().GlobalAcceleratorHostedZoneID(ctx)) data.ID = types.StringValue(acceleratorARN) - data.IpAddressType = flex.StringToFrameworkLegacy(ctx, accelerator.IpAddressType) + data.IpAddressType = flex.StringValueToFrameworkLegacy(ctx, accelerator.IpAddressType) data.IpSets = d.flattenIPSetsFramework(ctx, accelerator.IpSets) data.Name = flex.StringToFrameworkLegacy(ctx, accelerator.Name) - attributes, err := FindAcceleratorAttributesByARN(ctx, conn, acceleratorARN) + attributes, err := findAcceleratorAttributesByARN(ctx, conn, acceleratorARN) if err != nil { response.Diagnostics.AddError("reading Global Accelerator Accelerator attributes", err.Error()) @@ -181,7 +169,7 @@ func (d *dataSourceAccelerator) Read(ctx context.Context, request datasource.Rea response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -func (d *dataSourceAccelerator) flattenIPSetFramework(ctx context.Context, apiObject *globalaccelerator.IpSet) types.Object { +func (d *acceleratorDataSource) flattenIPSetFramework(ctx context.Context, apiObject *awstypes.IpSet) types.Object { attributeTypes := map[string]attr.Type{ "ip_addresses": types.ListType{ElemType: types.StringType}, "ip_family": types.StringType, @@ -192,14 +180,14 @@ func (d *dataSourceAccelerator) flattenIPSetFramework(ctx context.Context, apiOb } attributes := map[string]attr.Value{ - "ip_addresses": flex.FlattenFrameworkStringListLegacy(ctx, apiObject.IpAddresses), + "ip_addresses": flex.FlattenFrameworkStringValueListLegacy(ctx, apiObject.IpAddresses), "ip_family": flex.StringToFrameworkLegacy(ctx, apiObject.IpFamily), } return types.ObjectValueMust(attributeTypes, attributes) } -func (d *dataSourceAccelerator) flattenIPSetsFramework(ctx context.Context, apiObjects []*globalaccelerator.IpSet) types.List { +func (d *acceleratorDataSource) flattenIPSetsFramework(ctx context.Context, apiObjects []awstypes.IpSet) types.List { elementType := types.ObjectType{AttrTypes: map[string]attr.Type{ "ip_addresses": types.ListType{ElemType: types.StringType}, "ip_family": types.StringType, @@ -207,17 +195,13 @@ func (d *dataSourceAccelerator) flattenIPSetsFramework(ctx context.Context, apiO var elements []attr.Value for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - elements = append(elements, d.flattenIPSetFramework(ctx, apiObject)) + elements = append(elements, d.flattenIPSetFramework(ctx, &apiObject)) } return types.ListValueMust(elementType, elements) } -func (d *dataSourceAccelerator) flattenAcceleratorAttributesFramework(ctx context.Context, apiObject *globalaccelerator.AcceleratorAttributes) types.List { +func (d *acceleratorDataSource) flattenAcceleratorAttributesFramework(ctx context.Context, apiObject *awstypes.AcceleratorAttributes) types.List { attributeTypes := map[string]attr.Type{ "flow_logs_enabled": types.BoolType, "flow_logs_s3_bucket": types.StringType, @@ -240,7 +224,7 @@ func (d *dataSourceAccelerator) flattenAcceleratorAttributesFramework(ctx contex return types.ListValueMust(elementType, []attr.Value{types.ObjectValueMust(attributeTypes, attributes)}) } -type dataSourceAcceleratorData struct { +type acceleratorDataSourceModel struct { ARN fwtypes.ARN `tfsdk:"arn"` Attributes types.List `tfsdk:"attributes"` DnsName types.String `tfsdk:"dns_name"` diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index ce15945e679..6767f34bbd1 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -15,7 +15,8 @@ type servicePackage struct{} func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.ServicePackageFrameworkDataSource { return []*types.ServicePackageFrameworkDataSource{ { - Factory: newDataSourceAccelerator, + Factory: newAcceleratorDataSource, + Name: "Accelerator", }, } } From 5393e431fe1de5b53ead8a2cc0ebfdf9281d2f6c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 12:39:08 -0400 Subject: [PATCH 25/35] globalaccelerator: Migrate ARN helpers to AWS SDK for Go v2. --- internal/service/globalaccelerator/arn.go | 10 +++++----- internal/service/globalaccelerator/arn_test.go | 7 +++---- .../globalaccelerator/custom_routing_endpoint_group.go | 6 +++--- .../globalaccelerator/custom_routing_listener.go | 2 +- internal/service/globalaccelerator/endpoint_group.go | 8 ++++---- internal/service/globalaccelerator/listener.go | 2 +- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/internal/service/globalaccelerator/arn.go b/internal/service/globalaccelerator/arn.go index e02a0830622..a6db91eabf1 100644 --- a/internal/service/globalaccelerator/arn.go +++ b/internal/service/globalaccelerator/arn.go @@ -7,7 +7,7 @@ import ( "fmt" "strings" - "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go-v2/aws/arn" ) const ( @@ -15,9 +15,9 @@ const ( ARNService = "globalaccelerator" ) -// EndpointGroupARNToListenerARN converts an endpoint group ARN to a listener ARN. +// endpointGroupARNToListenerARN converts an endpoint group ARN to a listener ARN. // See https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglobalaccelerator.html#awsglobalaccelerator-resources-for-iam-policies. -func EndpointGroupARNToListenerARN(inputARN string) (string, error) { +func endpointGroupARNToListenerARN(inputARN string) (string, error) { parsedARN, err := arn.Parse(inputARN) if err != nil { @@ -45,9 +45,9 @@ func EndpointGroupARNToListenerARN(inputARN string) (string, error) { return outputARN, nil } -// ListenerOrEndpointGroupARNToAcceleratorARN converts a listener or endpoint group ARN to an accelerator ARN. +// listenerOrEndpointGroupARNToAcceleratorARN converts a listener or endpoint group ARN to an accelerator ARN. // See https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglobalaccelerator.html#awsglobalaccelerator-resources-for-iam-policies. -func ListenerOrEndpointGroupARNToAcceleratorARN(inputARN string) (string, error) { +func listenerOrEndpointGroupARNToAcceleratorARN(inputARN string) (string, error) { parsedARN, err := arn.Parse(inputARN) if err != nil { diff --git a/internal/service/globalaccelerator/arn_test.go b/internal/service/globalaccelerator/arn_test.go index 567bdd92a29..52b533ec04d 100644 --- a/internal/service/globalaccelerator/arn_test.go +++ b/internal/service/globalaccelerator/arn_test.go @@ -1,14 +1,13 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -package globalaccelerator_test +package globalaccelerator import ( "regexp" "testing" "github.com/YakDriver/regexache" - tfglobalaccelerator "github.com/hashicorp/terraform-provider-aws/internal/service/globalaccelerator" ) func TestEndpointGroupARNToListenerARN(t *testing.T) { @@ -52,7 +51,7 @@ func TestEndpointGroupARNToListenerARN(t *testing.T) { t.Run(testCase.TestName, func(t *testing.T) { t.Parallel() - got, err := tfglobalaccelerator.EndpointGroupARNToListenerARN(testCase.InputARN) + got, err := endpointGroupARNToListenerARN(testCase.InputARN) if err == nil && testCase.ExpectedError != nil { t.Fatalf("expected error %s, got no error", testCase.ExpectedError.String()) @@ -119,7 +118,7 @@ func TestListenerOrEndpointGroupARNToAcceleratorARN(t *testing.T) { t.Run(testCase.TestName, func(t *testing.T) { t.Parallel() - got, err := tfglobalaccelerator.ListenerOrEndpointGroupARNToAcceleratorARN(testCase.InputARN) + got, err := listenerOrEndpointGroupARNToAcceleratorARN(testCase.InputARN) if err == nil && testCase.ExpectedError != nil { t.Fatalf("expected error %s, got no error", testCase.ExpectedError.String()) diff --git a/internal/service/globalaccelerator/custom_routing_endpoint_group.go b/internal/service/globalaccelerator/custom_routing_endpoint_group.go index 4b7e2f58980..a0789b36996 100644 --- a/internal/service/globalaccelerator/custom_routing_endpoint_group.go +++ b/internal/service/globalaccelerator/custom_routing_endpoint_group.go @@ -125,7 +125,7 @@ func resourceCustomRoutingEndpointGroupCreate(ctx context.Context, d *schema.Res d.SetId(aws.StringValue(output.EndpointGroup.EndpointGroupArn)) - acceleratorARN, err := ListenerOrEndpointGroupARNToAcceleratorARN(d.Id()) + acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) @@ -171,7 +171,7 @@ func resourceCustomRoutingEndpointGroupRead(ctx context.Context, d *schema.Resou return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Custom Routing Endpoint Group (%s): %s", d.Id(), err) } - listenerARN, err := EndpointGroupARNToListenerARN(d.Id()) + listenerARN, err := endpointGroupARNToListenerARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) @@ -207,7 +207,7 @@ func resourceCustomRoutingEndpointGroupDelete(ctx context.Context, d *schema.Res return sdkdiag.AppendErrorf(diags, "deleting Global Accelerator Custom Routing Endpoint Group (%s): %s", d.Id(), err) } - acceleratorARN, err := ListenerOrEndpointGroupARNToAcceleratorARN(d.Id()) + acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) diff --git a/internal/service/globalaccelerator/custom_routing_listener.go b/internal/service/globalaccelerator/custom_routing_listener.go index 6862da3a2e6..25bf0aa00c0 100644 --- a/internal/service/globalaccelerator/custom_routing_listener.go +++ b/internal/service/globalaccelerator/custom_routing_listener.go @@ -112,7 +112,7 @@ func resourceCustomRoutingListenerRead(ctx context.Context, d *schema.ResourceDa return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Custom Routing Listener (%s): %s", d.Id(), err) } - acceleratorARN, err := ListenerOrEndpointGroupARNToAcceleratorARN(d.Id()) + acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index 7cb4e21839f..d758b635a5e 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -195,7 +195,7 @@ func resourceEndpointGroupCreate(ctx context.Context, d *schema.ResourceData, me d.SetId(aws.StringValue(resp.EndpointGroup.EndpointGroupArn)) - acceleratorARN, err := ListenerOrEndpointGroupARNToAcceleratorARN(d.Id()) + acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) @@ -225,7 +225,7 @@ func resourceEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Endpoint Group (%s): %s", d.Id(), err) } - listenerARN, err := EndpointGroupARNToListenerARN(d.Id()) + listenerARN, err := endpointGroupARNToListenerARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) @@ -301,7 +301,7 @@ func resourceEndpointGroupUpdate(ctx context.Context, d *schema.ResourceData, me return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Endpoint Group (%s): %s", d.Id(), err) } - acceleratorARN, err := ListenerOrEndpointGroupARNToAcceleratorARN(d.Id()) + acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) @@ -332,7 +332,7 @@ func resourceEndpointGroupDelete(ctx context.Context, d *schema.ResourceData, me return sdkdiag.AppendErrorf(diags, "deleting Global Accelerator Endpoint Group (%s): %s", d.Id(), err) } - acceleratorARN, err := ListenerOrEndpointGroupARNToAcceleratorARN(d.Id()) + acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) diff --git a/internal/service/globalaccelerator/listener.go b/internal/service/globalaccelerator/listener.go index 07895de892d..18f4b430971 100644 --- a/internal/service/globalaccelerator/listener.go +++ b/internal/service/globalaccelerator/listener.go @@ -127,7 +127,7 @@ func resourceListenerRead(ctx context.Context, d *schema.ResourceData, meta inte return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Listener (%s): %s", d.Id(), err) } - acceleratorARN, err := ListenerOrEndpointGroupARNToAcceleratorARN(d.Id()) + acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) if err != nil { return sdkdiag.AppendFromErr(diags, err) From 6a815b2e6345ddc5d51a0edb0111311dbd81c16c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 13:26:59 -0400 Subject: [PATCH 26/35] r/aws_globalaccelerator_listener: Migrate to AWS SDK for GO v2. --- .../service/globalaccelerator/exports_test.go | 2 + .../service/globalaccelerator/listener.go | 105 ++++++++---------- .../globalaccelerator/listener_test.go | 8 +- .../globalaccelerator/service_package_gen.go | 3 +- 4 files changed, 53 insertions(+), 65 deletions(-) diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index d341722a046..2df12350df7 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -7,7 +7,9 @@ package globalaccelerator var ( ResourceAccelerator = resourceAccelerator ResourceCrossAccountAttachment = newCrossAccountAttachmentResource + ResourceListener = resourceListener FindAcceleratorByARN = findAcceleratorByARN FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN + FindListenerByARN = findListenerByARN ) diff --git a/internal/service/globalaccelerator/listener.go b/internal/service/globalaccelerator/listener.go index 18f4b430971..dfb5a322329 100644 --- a/internal/service/globalaccelerator/listener.go +++ b/internal/service/globalaccelerator/listener.go @@ -8,21 +8,23 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "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/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/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" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -// @SDKResource("aws_globalaccelerator_listener") -func ResourceListener() *schema.Resource { +// @SDKResource("aws_globalaccelerator_listener", name="Listener") +func resourceListener() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceListenerCreate, ReadWithoutTimeout: resourceListenerRead, @@ -46,10 +48,10 @@ func ResourceListener() *schema.Resource { ForceNew: true, }, "client_affinity": { - Type: schema.TypeString, - Optional: true, - Default: globalaccelerator.ClientAffinityNone, - ValidateFunc: validation.StringInSlice(globalaccelerator.ClientAffinity_Values(), false), + Type: schema.TypeString, + Optional: true, + Default: awstypes.ClientAffinityNone, + ValidateDiagFunc: enum.Validate[awstypes.ClientAffinity](), }, "port_range": { Type: schema.TypeSet, @@ -72,9 +74,9 @@ func ResourceListener() *schema.Resource { }, }, "protocol": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(globalaccelerator.Protocol_Values(), false), + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.Protocol](), }, }, } @@ -82,29 +84,28 @@ func ResourceListener() *schema.Resource { func resourceListenerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) acceleratorARN := d.Get("accelerator_arn").(string) - input := &globalaccelerator.CreateListenerInput{ AcceleratorArn: aws.String(acceleratorARN), - ClientAffinity: aws.String(d.Get("client_affinity").(string)), + ClientAffinity: awstypes.ClientAffinity(d.Get("client_affinity").(string)), IdempotencyToken: aws.String(id.UniqueId()), PortRanges: expandPortRanges(d.Get("port_range").(*schema.Set).List()), - Protocol: aws.String(d.Get("protocol").(string)), + Protocol: awstypes.Protocol(d.Get("protocol").(string)), } - resp, err := conn.CreateListenerWithContext(ctx, input) + output, err := conn.CreateListener(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Global Accelerator Listener: %s", err) } - d.SetId(aws.StringValue(resp.Listener.ListenerArn)) + d.SetId(aws.ToString(output.Listener.ListenerArn)) // Creating a listener triggers the accelerator to change status to InPending. if _, err := waitAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", acceleratorARN, err) } return append(diags, resourceListenerRead(ctx, d, meta)...) @@ -112,10 +113,9 @@ func resourceListenerCreate(ctx context.Context, d *schema.ResourceData, meta in func resourceListenerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) - - listener, err := FindListenerByARN(ctx, conn, d.Id()) + listener, err := findListenerByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Global Accelerator Listener (%s) not found, removing from state", d.Id()) @@ -128,7 +128,6 @@ func resourceListenerRead(ctx context.Context, d *schema.ResourceData, meta inte } acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -145,18 +144,17 @@ func resourceListenerRead(ctx context.Context, d *schema.ResourceData, meta inte func resourceListenerUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) acceleratorARN := d.Get("accelerator_arn").(string) - input := &globalaccelerator.UpdateListenerInput{ - ClientAffinity: aws.String(d.Get("client_affinity").(string)), + ClientAffinity: awstypes.ClientAffinity(d.Get("client_affinity").(string)), ListenerArn: aws.String(d.Id()), PortRanges: expandPortRanges(d.Get("port_range").(*schema.Set).List()), - Protocol: aws.String(d.Get("protocol").(string)), + Protocol: awstypes.Protocol(d.Get("protocol").(string)), } - _, err := conn.UpdateListenerWithContext(ctx, input) + _, err := conn.UpdateListener(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Listener (%s): %s", d.Id(), err) @@ -164,7 +162,7 @@ func resourceListenerUpdate(ctx context.Context, d *schema.ResourceData, meta in // Updating a listener triggers the accelerator to change status to InPending. if _, err := waitAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", acceleratorARN, err) } return append(diags, resourceListenerRead(ctx, d, meta)...) @@ -172,16 +170,14 @@ func resourceListenerUpdate(ctx context.Context, d *schema.ResourceData, meta in func resourceListenerDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) - acceleratorARN := d.Get("accelerator_arn").(string) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) log.Printf("[DEBUG] Deleting Global Accelerator Listener: %s", d.Id()) - _, err := conn.DeleteListenerWithContext(ctx, &globalaccelerator.DeleteListenerInput{ + _, err := conn.DeleteListener(ctx, &globalaccelerator.DeleteListenerInput{ ListenerArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeListenerNotFoundException) { + if errs.IsA[*awstypes.ListenerNotFoundException](err) { return diags } @@ -190,25 +186,22 @@ func resourceListenerDelete(ctx context.Context, d *schema.ResourceData, meta in } // Deleting a listener triggers the accelerator to change status to InPending. + acceleratorARN := d.Get("accelerator_arn").(string) if _, err := waitAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutDelete)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", acceleratorARN, err) } return diags } -func FindListenerByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.Listener, error) { +func findListenerByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.Listener, error) { input := &globalaccelerator.DescribeListenerInput{ ListenerArn: aws.String(arn), } - return findListener(ctx, conn, input) -} - -func findListener(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeListenerInput) (*globalaccelerator.Listener, error) { - output, err := conn.DescribeListenerWithContext(ctx, input) + output, err := conn.DescribeListener(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeListenerNotFoundException) { + if errs.IsA[*awstypes.ListenerNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -226,30 +219,30 @@ func findListener(ctx context.Context, conn *globalaccelerator.GlobalAccelerator return output.Listener, nil } -func expandPortRange(tfMap map[string]interface{}) *globalaccelerator.PortRange { +func expandPortRange(tfMap map[string]interface{}) *awstypes.PortRange { if tfMap == nil { return nil } - apiObject := &globalaccelerator.PortRange{} + apiObject := &awstypes.PortRange{} if v, ok := tfMap["from_port"].(int); ok && v != 0 { - apiObject.FromPort = aws.Int64(int64(v)) + apiObject.FromPort = aws.Int32(int32(v)) } if v, ok := tfMap["to_port"].(int); ok && v != 0 { - apiObject.ToPort = aws.Int64(int64(v)) + apiObject.ToPort = aws.Int32(int32(v)) } return apiObject } -func expandPortRanges(tfList []interface{}) []*globalaccelerator.PortRange { +func expandPortRanges(tfList []interface{}) []awstypes.PortRange { if len(tfList) == 0 { return nil } - var apiObjects []*globalaccelerator.PortRange + var apiObjects []awstypes.PortRange for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) @@ -264,13 +257,13 @@ func expandPortRanges(tfList []interface{}) []*globalaccelerator.PortRange { continue } - apiObjects = append(apiObjects, apiObject) + apiObjects = append(apiObjects, *apiObject) } return apiObjects } -func flattenPortRange(apiObject *globalaccelerator.PortRange) map[string]interface{} { +func flattenPortRange(apiObject *awstypes.PortRange) map[string]interface{} { if apiObject == nil { return nil } @@ -278,17 +271,17 @@ func flattenPortRange(apiObject *globalaccelerator.PortRange) map[string]interfa tfMap := map[string]interface{}{} if v := apiObject.FromPort; v != nil { - tfMap["from_port"] = aws.Int64Value(v) + tfMap["from_port"] = aws.ToInt32(v) } if v := apiObject.ToPort; v != nil { - tfMap["to_port"] = aws.Int64Value(v) + tfMap["to_port"] = aws.ToInt32(v) } return tfMap } -func flattenPortRanges(apiObjects []*globalaccelerator.PortRange) []interface{} { +func flattenPortRanges(apiObjects []awstypes.PortRange) []interface{} { if len(apiObjects) == 0 { return nil } @@ -296,11 +289,7 @@ func flattenPortRanges(apiObjects []*globalaccelerator.PortRange) []interface{} var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenPortRange(apiObject)) + tfList = append(tfList, flattenPortRange(&apiObject)) } return tfList diff --git a/internal/service/globalaccelerator/listener_test.go b/internal/service/globalaccelerator/listener_test.go index 0d39c5f000a..7cb988d6aaf 100644 --- a/internal/service/globalaccelerator/listener_test.go +++ b/internal/service/globalaccelerator/listener_test.go @@ -112,16 +112,12 @@ func TestAccGlobalAcceleratorListener_update(t *testing.T) { func testAccCheckListenerExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Global Accelerator Listener ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) _, err := tfglobalaccelerator.FindListenerByARN(ctx, conn, rs.Primary.ID) @@ -131,7 +127,7 @@ func testAccCheckListenerExists(ctx context.Context, n string) resource.TestChec func testAccCheckListenerDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_globalaccelerator_listener" { diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index 6767f34bbd1..52fe2dad43a 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -73,8 +73,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka TypeName: "aws_globalaccelerator_endpoint_group", }, { - Factory: ResourceListener, + Factory: resourceListener, TypeName: "aws_globalaccelerator_listener", + Name: "Listener", }, } } From b5e99b11bcff65a16d188bd6512a33af6d47a3b5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 13:38:11 -0400 Subject: [PATCH 27/35] r/aws_globalaccelerator_endpoint_group: Migrate to AWS SDK for GO v2. --- .../globalaccelerator/endpoint_group.go | 142 ++++++++---------- .../globalaccelerator/endpoint_group_test.go | 34 ++--- .../service/globalaccelerator/exports_test.go | 1 + .../globalaccelerator/service_package_gen.go | 3 +- 4 files changed, 80 insertions(+), 100 deletions(-) diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index d758b635a5e..5f8346f6391 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -8,22 +8,24 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "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/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/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" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_globalaccelerator_endpoint_group") -func ResourceEndpointGroup() *schema.Resource { +// @SDKResource("aws_globalaccelerator_endpoint_group", name="Endpoint Group") +func resourceEndpointGroup() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceEndpointGroupCreate, ReadWithoutTimeout: resourceEndpointGroupRead, @@ -94,10 +96,10 @@ func ResourceEndpointGroup() *schema.Resource { ValidateFunc: validation.IsPortNumber, }, "health_check_protocol": { - Type: schema.TypeString, - Optional: true, - Default: globalaccelerator.HealthCheckProtocolTcp, - ValidateFunc: validation.StringInSlice(globalaccelerator.HealthCheckProtocol_Values(), false), + Type: schema.TypeString, + Optional: true, + Default: awstypes.HealthCheckProtocolTcp, + ValidateDiagFunc: enum.Validate[awstypes.HealthCheckProtocol](), }, "listener_arn": { Type: schema.TypeString, @@ -142,8 +144,7 @@ func ResourceEndpointGroup() *schema.Resource { func resourceEndpointGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) input := &globalaccelerator.CreateEndpointGroupInput{ EndpointGroupRegion: aws.String(meta.(*conns.AWSClient).Region), @@ -160,7 +161,7 @@ func resourceEndpointGroupCreate(ctx context.Context, d *schema.ResourceData, me } if v, ok := d.GetOk("health_check_interval_seconds"); ok { - input.HealthCheckIntervalSeconds = aws.Int64(int64(v.(int))) + input.HealthCheckIntervalSeconds = aws.Int32(int32(v.(int))) } if v, ok := d.GetOk("health_check_path"); ok { @@ -168,11 +169,11 @@ func resourceEndpointGroupCreate(ctx context.Context, d *schema.ResourceData, me } if v, ok := d.GetOk("health_check_port"); ok { - input.HealthCheckPort = aws.Int64(int64(v.(int))) + input.HealthCheckPort = aws.Int32(int32(v.(int))) } if v, ok := d.GetOk("health_check_protocol"); ok { - input.HealthCheckProtocol = aws.String(v.(string)) + input.HealthCheckProtocol = awstypes.HealthCheckProtocol(v.(string)) } if v, ok := d.GetOk("port_override"); ok && v.(*schema.Set).Len() > 0 { @@ -180,29 +181,28 @@ func resourceEndpointGroupCreate(ctx context.Context, d *schema.ResourceData, me } if v, ok := d.GetOk("threshold_count"); ok { - input.ThresholdCount = aws.Int64(int64(v.(int))) + input.ThresholdCount = aws.Int32(int32(v.(int))) } if v, ok := d.Get("traffic_dial_percentage").(float64); ok { - input.TrafficDialPercentage = aws.Float64(v) + input.TrafficDialPercentage = aws.Float32(float32(v)) } - resp, err := conn.CreateEndpointGroupWithContext(ctx, input) + output, err := conn.CreateEndpointGroup(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Global Accelerator Endpoint Group: %s", err) } - d.SetId(aws.StringValue(resp.EndpointGroup.EndpointGroupArn)) + d.SetId(aws.ToString(output.EndpointGroup.EndpointGroupArn)) acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } if _, err := waitAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", acceleratorARN, err) } return append(diags, resourceEndpointGroupRead(ctx, d, meta)...) @@ -210,8 +210,7 @@ func resourceEndpointGroupCreate(ctx context.Context, d *schema.ResourceData, me func resourceEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) endpointGroup, err := FindEndpointGroupByARN(ctx, conn, d.Id()) @@ -226,7 +225,6 @@ func resourceEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta } listenerARN, err := endpointGroupARNToListenerARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -252,8 +250,7 @@ func resourceEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta func resourceEndpointGroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) input := &globalaccelerator.UpdateEndpointGroupInput{ EndpointGroupArn: aws.String(d.Id()), @@ -262,11 +259,11 @@ func resourceEndpointGroupUpdate(ctx context.Context, d *schema.ResourceData, me if v, ok := d.GetOk("endpoint_configuration"); ok && v.(*schema.Set).Len() > 0 { input.EndpointConfigurations = expandEndpointConfigurations(v.(*schema.Set).List()) } else { - input.EndpointConfigurations = []*globalaccelerator.EndpointConfiguration{} + input.EndpointConfigurations = []awstypes.EndpointConfiguration{} } if v, ok := d.GetOk("health_check_interval_seconds"); ok { - input.HealthCheckIntervalSeconds = aws.Int64(int64(v.(int))) + input.HealthCheckIntervalSeconds = aws.Int32(int32(v.(int))) } if v, ok := d.GetOk("health_check_path"); ok { @@ -274,41 +271,40 @@ func resourceEndpointGroupUpdate(ctx context.Context, d *schema.ResourceData, me } if v, ok := d.GetOk("health_check_port"); ok { - input.HealthCheckPort = aws.Int64(int64(v.(int))) + input.HealthCheckPort = aws.Int32(int32(v.(int))) } if v, ok := d.GetOk("health_check_protocol"); ok { - input.HealthCheckProtocol = aws.String(v.(string)) + input.HealthCheckProtocol = awstypes.HealthCheckProtocol(v.(string)) } if v, ok := d.GetOk("port_override"); ok && v.(*schema.Set).Len() > 0 { input.PortOverrides = expandPortOverrides(v.(*schema.Set).List()) } else { - input.PortOverrides = []*globalaccelerator.PortOverride{} + input.PortOverrides = []awstypes.PortOverride{} } if v, ok := d.GetOk("threshold_count"); ok { - input.ThresholdCount = aws.Int64(int64(v.(int))) + input.ThresholdCount = aws.Int32(int32(v.(int))) } if v, ok := d.Get("traffic_dial_percentage").(float64); ok { - input.TrafficDialPercentage = aws.Float64(v) + input.TrafficDialPercentage = aws.Float32(float32(v)) } - _, err := conn.UpdateEndpointGroupWithContext(ctx, input) + _, err := conn.UpdateEndpointGroup(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Endpoint Group (%s): %s", d.Id(), err) } acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } if _, err := waitAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", acceleratorARN, err) } return append(diags, resourceEndpointGroupRead(ctx, d, meta)...) @@ -316,15 +312,14 @@ func resourceEndpointGroupUpdate(ctx context.Context, d *schema.ResourceData, me func resourceEndpointGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) log.Printf("[DEBUG] Deleting Global Accelerator Endpoint Group: %s", d.Id()) - _, err := conn.DeleteEndpointGroupWithContext(ctx, &globalaccelerator.DeleteEndpointGroupInput{ + _, err := conn.DeleteEndpointGroup(ctx, &globalaccelerator.DeleteEndpointGroupInput{ EndpointGroupArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeEndpointGroupNotFoundException) { + if errs.IsA[*awstypes.EndpointGroupNotFoundException](err) { return diags } @@ -333,30 +328,25 @@ func resourceEndpointGroupDelete(ctx context.Context, d *schema.ResourceData, me } acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } if _, err := waitAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutDelete)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Accelerator (%s) deploy: %s", acceleratorARN, err) } return diags } -func FindEndpointGroupByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.EndpointGroup, error) { +func FindEndpointGroupByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.EndpointGroup, error) { input := &globalaccelerator.DescribeEndpointGroupInput{ EndpointGroupArn: aws.String(arn), } - return findEndpointGroup(ctx, conn, input) -} - -func findEndpointGroup(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeEndpointGroupInput) (*globalaccelerator.EndpointGroup, error) { - output, err := conn.DescribeEndpointGroupWithContext(ctx, input) + output, err := conn.DescribeEndpointGroup(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeEndpointGroupNotFoundException) { + if errs.IsA[*awstypes.EndpointGroupNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -374,12 +364,12 @@ func findEndpointGroup(ctx context.Context, conn *globalaccelerator.GlobalAccele return output.EndpointGroup, nil } -func expandEndpointConfiguration(tfMap map[string]interface{}) *globalaccelerator.EndpointConfiguration { +func expandEndpointConfiguration(tfMap map[string]interface{}) *awstypes.EndpointConfiguration { if tfMap == nil { return nil } - apiObject := &globalaccelerator.EndpointConfiguration{} + apiObject := &awstypes.EndpointConfiguration{} if v, ok := tfMap["client_ip_preservation_enabled"].(bool); ok { apiObject.ClientIPPreservationEnabled = aws.Bool(v) @@ -390,18 +380,18 @@ func expandEndpointConfiguration(tfMap map[string]interface{}) *globalaccelerato } if v, ok := tfMap["weight"].(int); ok { - apiObject.Weight = aws.Int64(int64(v)) + apiObject.Weight = aws.Int32(int32(v)) } return apiObject } -func expandEndpointConfigurations(tfList []interface{}) []*globalaccelerator.EndpointConfiguration { +func expandEndpointConfigurations(tfList []interface{}) []awstypes.EndpointConfiguration { if len(tfList) == 0 { return nil } - var apiObjects []*globalaccelerator.EndpointConfiguration + var apiObjects []awstypes.EndpointConfiguration for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) @@ -416,36 +406,36 @@ func expandEndpointConfigurations(tfList []interface{}) []*globalaccelerator.End continue } - apiObjects = append(apiObjects, apiObject) + apiObjects = append(apiObjects, *apiObject) } return apiObjects } -func expandPortOverride(tfMap map[string]interface{}) *globalaccelerator.PortOverride { +func expandPortOverride(tfMap map[string]interface{}) *awstypes.PortOverride { if tfMap == nil { return nil } - apiObject := &globalaccelerator.PortOverride{} + apiObject := &awstypes.PortOverride{} if v, ok := tfMap["endpoint_port"].(int); ok && v != 0 { - apiObject.EndpointPort = aws.Int64(int64(v)) + apiObject.EndpointPort = aws.Int32(int32(v)) } if v, ok := tfMap["listener_port"].(int); ok && v != 0 { - apiObject.ListenerPort = aws.Int64(int64(v)) + apiObject.ListenerPort = aws.Int32(int32(v)) } return apiObject } -func expandPortOverrides(tfList []interface{}) []*globalaccelerator.PortOverride { +func expandPortOverrides(tfList []interface{}) []awstypes.PortOverride { if len(tfList) == 0 { return nil } - var apiObjects []*globalaccelerator.PortOverride + var apiObjects []awstypes.PortOverride for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) @@ -460,13 +450,13 @@ func expandPortOverrides(tfList []interface{}) []*globalaccelerator.PortOverride continue } - apiObjects = append(apiObjects, apiObject) + apiObjects = append(apiObjects, *apiObject) } return apiObjects } -func flattenEndpointDescription(apiObject *globalaccelerator.EndpointDescription) map[string]interface{} { +func flattenEndpointDescription(apiObject *awstypes.EndpointDescription) map[string]interface{} { if apiObject == nil { return nil } @@ -474,21 +464,21 @@ func flattenEndpointDescription(apiObject *globalaccelerator.EndpointDescription tfMap := map[string]interface{}{} if v := apiObject.ClientIPPreservationEnabled; v != nil { - tfMap["client_ip_preservation_enabled"] = aws.BoolValue(v) + tfMap["client_ip_preservation_enabled"] = aws.ToBool(v) } if v := apiObject.EndpointId; v != nil { - tfMap["endpoint_id"] = aws.StringValue(v) + tfMap["endpoint_id"] = aws.ToString(v) } if v := apiObject.Weight; v != nil { - tfMap["weight"] = aws.Int64Value(v) + tfMap["weight"] = aws.ToInt32(v) } return tfMap } -func flattenEndpointDescriptions(apiObjects []*globalaccelerator.EndpointDescription) []interface{} { +func flattenEndpointDescriptions(apiObjects []awstypes.EndpointDescription) []interface{} { if len(apiObjects) == 0 { return nil } @@ -496,17 +486,13 @@ func flattenEndpointDescriptions(apiObjects []*globalaccelerator.EndpointDescrip var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenEndpointDescription(apiObject)) + tfList = append(tfList, flattenEndpointDescription(&apiObject)) } return tfList } -func flattenPortOverride(apiObject *globalaccelerator.PortOverride) map[string]interface{} { +func flattenPortOverride(apiObject *awstypes.PortOverride) map[string]interface{} { if apiObject == nil { return nil } @@ -514,17 +500,17 @@ func flattenPortOverride(apiObject *globalaccelerator.PortOverride) map[string]i tfMap := map[string]interface{}{} if v := apiObject.EndpointPort; v != nil { - tfMap["endpoint_port"] = aws.Int64Value(v) + tfMap["endpoint_port"] = aws.ToInt32(v) } if v := apiObject.ListenerPort; v != nil { - tfMap["listener_port"] = aws.Int64Value(v) + tfMap["listener_port"] = aws.ToInt32(v) } return tfMap } -func flattenPortOverrides(apiObjects []*globalaccelerator.PortOverride) []interface{} { +func flattenPortOverrides(apiObjects []awstypes.PortOverride) []interface{} { if len(apiObjects) == 0 { return nil } @@ -532,11 +518,7 @@ func flattenPortOverrides(apiObjects []*globalaccelerator.PortOverride) []interf var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenPortOverride(apiObject)) + tfList = append(tfList, flattenPortOverride(&apiObject)) } return tfList diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index 94a0d7e3f22..daba75804e6 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/aws" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/globalaccelerator" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -25,7 +25,7 @@ import ( func TestAccGlobalAcceleratorEndpointGroup_basic(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup resourceName := "aws_globalaccelerator_endpoint_group.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -63,7 +63,7 @@ func TestAccGlobalAcceleratorEndpointGroup_basic(t *testing.T) { func TestAccGlobalAcceleratorEndpointGroup_disappears(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup resourceName := "aws_globalaccelerator_endpoint_group.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -87,7 +87,7 @@ func TestAccGlobalAcceleratorEndpointGroup_disappears(t *testing.T) { func TestAccGlobalAcceleratorEndpointGroup_ALBEndpoint_clientIP(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup var vpc ec2.Vpc resourceName := "aws_globalaccelerator_endpoint_group.test" albResourceName := "aws_lb.test" @@ -162,7 +162,7 @@ func TestAccGlobalAcceleratorEndpointGroup_ALBEndpoint_clientIP(t *testing.T) { func TestAccGlobalAcceleratorEndpointGroup_instanceEndpoint(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup var vpc ec2.Vpc resourceName := "aws_globalaccelerator_endpoint_group.test" instanceResourceName := "aws_instance.test" @@ -215,7 +215,7 @@ func TestAccGlobalAcceleratorEndpointGroup_instanceEndpoint(t *testing.T) { func TestAccGlobalAcceleratorEndpointGroup_multiRegion(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup resourceName := "aws_globalaccelerator_endpoint_group.test" eipResourceName := "aws_eip.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -259,7 +259,7 @@ func TestAccGlobalAcceleratorEndpointGroup_multiRegion(t *testing.T) { func TestAccGlobalAcceleratorEndpointGroup_portOverrides(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup resourceName := "aws_globalaccelerator_endpoint_group.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -326,7 +326,7 @@ func TestAccGlobalAcceleratorEndpointGroup_portOverrides(t *testing.T) { func TestAccGlobalAcceleratorEndpointGroup_tcpHealthCheckProtocol(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup resourceName := "aws_globalaccelerator_endpoint_group.test" eipResourceName := "aws_eip.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -370,7 +370,7 @@ func TestAccGlobalAcceleratorEndpointGroup_tcpHealthCheckProtocol(t *testing.T) func TestAccGlobalAcceleratorEndpointGroup_update(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.EndpointGroup + var v awstypes.EndpointGroup resourceName := "aws_globalaccelerator_endpoint_group.test" eipResourceName := "aws_eip.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -429,18 +429,14 @@ func TestAccGlobalAcceleratorEndpointGroup_update(t *testing.T) { }) } -func testAccCheckEndpointGroupExists(ctx context.Context, name string, v *globalaccelerator.EndpointGroup) resource.TestCheckFunc { +func testAccCheckEndpointGroupExists(ctx context.Context, name string, v *awstypes.EndpointGroup) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - rs, ok := s.RootModule().Resources[name] if !ok { return fmt.Errorf("Not found: %s", name) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Global Accelerator Endpoint Group ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) endpointGroup, err := tfglobalaccelerator.FindEndpointGroupByARN(ctx, conn, rs.Primary.ID) @@ -456,7 +452,7 @@ func testAccCheckEndpointGroupExists(ctx context.Context, name string, v *global func testAccCheckEndpointGroupDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_globalaccelerator_endpoint_group" { @@ -486,7 +482,7 @@ func testAccCheckEndpointGroupDeleteSecurityGroup(ctx context.Context, vpc *ec2. meta := acctest.Provider.Meta() conn := meta.(*conns.AWSClient).EC2Conn(ctx) - v, err := tfec2.FindSecurityGroupByNameAndVPCIDAndOwnerID(ctx, conn, "GlobalAccelerator", aws.StringValue(vpc.VpcId), aws.StringValue(vpc.OwnerId)) + v, err := tfec2.FindSecurityGroupByNameAndVPCIDAndOwnerID(ctx, conn, "GlobalAccelerator", aws.ToString(vpc.VpcId), aws.ToString(vpc.OwnerId)) if tfresource.NotFound(err) { // Already gone. @@ -499,7 +495,7 @@ func testAccCheckEndpointGroupDeleteSecurityGroup(ctx context.Context, vpc *ec2. r := tfec2.ResourceSecurityGroup() d := r.Data(nil) - d.SetId(aws.StringValue(v.GroupId)) + d.SetId(aws.ToString(v.GroupId)) d.Set("revoke_rules_on_delete", true) err = acctest.DeleteResource(ctx, r, d, meta) diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index 2df12350df7..d430e69de71 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -7,6 +7,7 @@ package globalaccelerator var ( ResourceAccelerator = resourceAccelerator ResourceCrossAccountAttachment = newCrossAccountAttachmentResource + ResourceEndpointGroup = resourceEndpointGroup ResourceListener = resourceListener FindAcceleratorByARN = findAcceleratorByARN diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index 52fe2dad43a..ba475605fd2 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -69,8 +69,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka TypeName: "aws_globalaccelerator_custom_routing_listener", }, { - Factory: ResourceEndpointGroup, + Factory: resourceEndpointGroup, TypeName: "aws_globalaccelerator_endpoint_group", + Name: "Endpoint Group", }, { Factory: resourceListener, From 3d4bedd482c8832343b814f33172d30dc37e7b54 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 15:23:53 -0400 Subject: [PATCH 28/35] r/aws_globalaccelerator_custom_routing_listener: Migrate to AWS SDK for GO v2. --- .../custom_routing_listener.go | 53 +++++++++---------- .../custom_routing_listener_test.go | 16 +++--- .../service/globalaccelerator/exports_test.go | 2 + .../globalaccelerator/service_package_gen.go | 3 +- 4 files changed, 34 insertions(+), 40 deletions(-) diff --git a/internal/service/globalaccelerator/custom_routing_listener.go b/internal/service/globalaccelerator/custom_routing_listener.go index 25bf0aa00c0..3f4e50137ca 100644 --- a/internal/service/globalaccelerator/custom_routing_listener.go +++ b/internal/service/globalaccelerator/custom_routing_listener.go @@ -8,21 +8,22 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "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/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/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/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -// @SDKResource("aws_globalaccelerator_custom_routing_listener") -func ResourceCustomRoutingListener() *schema.Resource { +// @SDKResource("aws_globalaccelerator_custom_routing_listener", name="Custom Routing Listener") +func resourceCustomRoutingListener() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceCustomRoutingListenerCreate, ReadWithoutTimeout: resourceCustomRoutingListenerRead, @@ -71,7 +72,7 @@ func ResourceCustomRoutingListener() *schema.Resource { func resourceCustomRoutingListenerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) acceleratorARN := d.Get("accelerator_arn").(string) input := &globalaccelerator.CreateCustomRoutingListenerInput{ @@ -80,17 +81,17 @@ func resourceCustomRoutingListenerCreate(ctx context.Context, d *schema.Resource PortRanges: expandPortRanges(d.Get("port_range").(*schema.Set).List()), } - output, err := conn.CreateCustomRoutingListenerWithContext(ctx, input) + output, err := conn.CreateCustomRoutingListener(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Global Accelerator Custom Routing Listener: %s", err) } - d.SetId(aws.StringValue(output.Listener.ListenerArn)) + d.SetId(aws.ToString(output.Listener.ListenerArn)) // Creating a listener triggers the accelerator to change status to InPending. if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", acceleratorARN, err) } return append(diags, resourceCustomRoutingListenerRead(ctx, d, meta)...) @@ -98,9 +99,9 @@ func resourceCustomRoutingListenerCreate(ctx context.Context, d *schema.Resource func resourceCustomRoutingListenerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - listener, err := FindCustomRoutingListenerByARN(ctx, conn, d.Id()) + listener, err := findCustomRoutingListenerByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Global Accelerator Custom Routing Listener (%s) not found, removing from state", d.Id()) @@ -113,7 +114,6 @@ func resourceCustomRoutingListenerRead(ctx context.Context, d *schema.ResourceDa } acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -128,15 +128,15 @@ func resourceCustomRoutingListenerRead(ctx context.Context, d *schema.ResourceDa func resourceCustomRoutingListenerUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) - acceleratorARN := d.Get("accelerator_arn").(string) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) + acceleratorARN := d.Get("accelerator_arn").(string) input := &globalaccelerator.UpdateCustomRoutingListenerInput{ ListenerArn: aws.String(d.Id()), PortRanges: expandPortRanges(d.Get("port_range").(*schema.Set).List()), } - _, err := conn.UpdateCustomRoutingListenerWithContext(ctx, input) + _, err := conn.UpdateCustomRoutingListener(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Custom Routing Listener (%s): %s", d.Id(), err) @@ -144,7 +144,7 @@ func resourceCustomRoutingListenerUpdate(ctx context.Context, d *schema.Resource // Updating a listener triggers the accelerator to change status to InPending. if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", acceleratorARN, err) } return append(diags, resourceCustomRoutingListenerRead(ctx, d, meta)...) @@ -152,16 +152,14 @@ func resourceCustomRoutingListenerUpdate(ctx context.Context, d *schema.Resource func resourceCustomRoutingListenerDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) - - acceleratorARN := d.Get("accelerator_arn").(string) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) log.Printf("[DEBUG] Deleting Global Accelerator Custom Routing Listener (%s)", d.Id()) - _, err := conn.DeleteCustomRoutingListenerWithContext(ctx, &globalaccelerator.DeleteCustomRoutingListenerInput{ + _, err := conn.DeleteCustomRoutingListener(ctx, &globalaccelerator.DeleteCustomRoutingListenerInput{ ListenerArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeListenerNotFoundException) { + if errs.IsA[*awstypes.ListenerNotFoundException](err) { return diags } @@ -170,25 +168,22 @@ func resourceCustomRoutingListenerDelete(ctx context.Context, d *schema.Resource } // Deleting a listener triggers the accelerator to change status to InPending. + acceleratorARN := d.Get("accelerator_arn").(string) if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutDelete)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", acceleratorARN, err) } return diags } -func FindCustomRoutingListenerByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.CustomRoutingListener, error) { +func findCustomRoutingListenerByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.CustomRoutingListener, error) { input := &globalaccelerator.DescribeCustomRoutingListenerInput{ ListenerArn: aws.String(arn), } - return findCustomRoutingListener(ctx, conn, input) -} - -func findCustomRoutingListener(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeCustomRoutingListenerInput) (*globalaccelerator.CustomRoutingListener, error) { - output, err := conn.DescribeCustomRoutingListenerWithContext(ctx, input) + output, err := conn.DescribeCustomRoutingListener(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeListenerNotFoundException) { + if errs.IsA[*awstypes.ListenerNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, diff --git a/internal/service/globalaccelerator/custom_routing_listener_test.go b/internal/service/globalaccelerator/custom_routing_listener_test.go index 426776943ae..157500351cb 100644 --- a/internal/service/globalaccelerator/custom_routing_listener_test.go +++ b/internal/service/globalaccelerator/custom_routing_listener_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/service/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -21,7 +21,7 @@ import ( func TestAccGlobalAcceleratorCustomRoutingListener_basic(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.CustomRoutingListener + var v awstypes.CustomRoutingListener resourceName := "aws_globalaccelerator_custom_routing_listener.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -57,7 +57,7 @@ func TestAccGlobalAcceleratorCustomRoutingListener_basic(t *testing.T) { func TestAccGlobalAcceleratorCustomRoutingListener_disappears(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.CustomRoutingListener + var v awstypes.CustomRoutingListener resourceName := "aws_globalaccelerator_custom_routing_listener.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -79,18 +79,14 @@ func TestAccGlobalAcceleratorCustomRoutingListener_disappears(t *testing.T) { }) } -func testAccCheckCustomRoutingListenerExists(ctx context.Context, n string, v *globalaccelerator.CustomRoutingListener) resource.TestCheckFunc { +func testAccCheckCustomRoutingListenerExists(ctx context.Context, n string, v *awstypes.CustomRoutingListener) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Global Accelerator Custom Routing Listener ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) output, err := tfglobalaccelerator.FindCustomRoutingListenerByARN(ctx, conn, rs.Primary.ID) @@ -106,7 +102,7 @@ func testAccCheckCustomRoutingListenerExists(ctx context.Context, n string, v *g func testAccCheckCustomRoutingListenerDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_globalaccelerator_custom_routing_listener" { diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index d430e69de71..56e06b25568 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -7,10 +7,12 @@ package globalaccelerator var ( ResourceAccelerator = resourceAccelerator ResourceCrossAccountAttachment = newCrossAccountAttachmentResource + ResourceCustomRoutingListener = resourceCustomRoutingListener ResourceEndpointGroup = resourceEndpointGroup ResourceListener = resourceListener FindAcceleratorByARN = findAcceleratorByARN FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN + FindCustomRoutingListenerByARN = findCustomRoutingListenerByARN FindListenerByARN = findListenerByARN ) diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index ba475605fd2..412e8c2c0f3 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -65,8 +65,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka TypeName: "aws_globalaccelerator_custom_routing_endpoint_group", }, { - Factory: ResourceCustomRoutingListener, + Factory: resourceCustomRoutingListener, TypeName: "aws_globalaccelerator_custom_routing_listener", + Name: "Custom Routing Listener", }, { Factory: resourceEndpointGroup, From 3500bd6ab91464e31935ee7a912fdf39434fe083 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 15:32:29 -0400 Subject: [PATCH 29/35] r/aws_globalaccelerator_custom_routing_accelerator: Migrate to AWS SDK for GO v2. --- .../custom_routing_accelerator.go | 110 +++++++++--------- .../custom_routing_accelerator_data_source.go | 2 +- .../custom_routing_accelerator_test.go | 8 +- .../service/globalaccelerator/exports_test.go | 20 ++-- .../globalaccelerator/service_package_gen.go | 2 +- 5 files changed, 67 insertions(+), 75 deletions(-) diff --git a/internal/service/globalaccelerator/custom_routing_accelerator.go b/internal/service/globalaccelerator/custom_routing_accelerator.go index 4563c437c63..444de99c2ca 100644 --- a/internal/service/globalaccelerator/custom_routing_accelerator.go +++ b/internal/service/globalaccelerator/custom_routing_accelerator.go @@ -9,15 +9,17 @@ import ( "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "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/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/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" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -28,7 +30,7 @@ import ( // @SDKResource("aws_globalaccelerator_custom_routing_accelerator", name="Custom Routing Accelerator") // @Tags(identifierAttribute="id") -func ResourceCustomRoutingAccelerator() *schema.Resource { +func resourceCustomRoutingAccelerator() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceCustomRoutingAcceleratorCreate, ReadWithoutTimeout: resourceCustomRoutingAcceleratorRead, @@ -84,10 +86,10 @@ func ResourceCustomRoutingAccelerator() *schema.Resource { Computed: true, }, "ip_address_type": { - Type: schema.TypeString, - Optional: true, - Default: globalaccelerator.IpAddressTypeIpv4, - ValidateFunc: validation.StringInSlice(globalaccelerator.IpAddressType_Values(), false), + Type: schema.TypeString, + Optional: true, + Default: awstypes.IpAddressTypeIpv4, + ValidateDiagFunc: enum.Validate[awstypes.IpAddressType](), }, "ip_addresses": { Type: schema.TypeList, @@ -132,46 +134,46 @@ func ResourceCustomRoutingAccelerator() *schema.Resource { func resourceCustomRoutingAcceleratorCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) name := d.Get("name").(string) input := &globalaccelerator.CreateCustomRoutingAcceleratorInput{ + Enabled: aws.Bool(d.Get("enabled").(bool)), Name: aws.String(name), IdempotencyToken: aws.String(id.UniqueId()), - Enabled: aws.Bool(d.Get("enabled").(bool)), Tags: getTagsIn(ctx), } if v, ok := d.GetOk("ip_address_type"); ok { - input.IpAddressType = aws.String(v.(string)) + input.IpAddressType = awstypes.IpAddressType(v.(string)) } if v, ok := d.GetOk("ip_addresses"); ok && len(v.([]interface{})) > 0 { - input.IpAddresses = flex.ExpandStringList(v.([]interface{})) + input.IpAddresses = flex.ExpandStringValueList(v.([]interface{})) } - output, err := conn.CreateCustomRoutingAcceleratorWithContext(ctx, input) + output, err := conn.CreateCustomRoutingAccelerator(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Global Accelerator Custom Routing Accelerator (%s): %s", name, err) } - d.SetId(aws.StringValue(output.Accelerator.AcceleratorArn)) + d.SetId(aws.ToString(output.Accelerator.AcceleratorArn)) if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", d.Id(), err) } if v, ok := d.GetOk("attributes"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { input := expandUpdateAcceleratorAttributesInput(v.([]interface{})[0].(map[string]interface{})) input.AcceleratorArn = aws.String(d.Id()) - if _, err := conn.UpdateAcceleratorAttributesWithContext(ctx, input); err != nil { + if _, err := conn.UpdateAcceleratorAttributes(ctx, input); err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Custom Routing Accelerator (%s) attributes: %s", d.Id(), err) } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", d.Id(), err) } } @@ -180,9 +182,9 @@ func resourceCustomRoutingAcceleratorCreate(ctx context.Context, d *schema.Resou func resourceCustomRoutingAcceleratorRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - accelerator, err := FindCustomRoutingAcceleratorByARN(ctx, conn, d.Id()) + accelerator, err := findCustomRoutingAcceleratorByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Global Accelerator Custom Routing Accelerator (%s) not found, removing from state", d.Id()) @@ -203,7 +205,7 @@ func resourceCustomRoutingAcceleratorRead(ctx context.Context, d *schema.Resourc } d.Set("name", accelerator.Name) - acceleratorAttributes, err := FindCustomRoutingAcceleratorAttributesByARN(ctx, conn, d.Id()) + acceleratorAttributes, err := findCustomRoutingAcceleratorAttributesByARN(ctx, conn, d.Id()) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Custom Routing Accelerator (%s) attributes: %s", d.Id(), err) @@ -218,7 +220,7 @@ func resourceCustomRoutingAcceleratorRead(ctx context.Context, d *schema.Resourc func resourceCustomRoutingAcceleratorUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) if d.HasChanges("name", "ip_address_type", "enabled") { input := &globalaccelerator.UpdateCustomRoutingAcceleratorInput{ @@ -228,17 +230,17 @@ func resourceCustomRoutingAcceleratorUpdate(ctx context.Context, d *schema.Resou } if v, ok := d.GetOk("ip_address_type"); ok { - input.IpAddressType = aws.String(v.(string)) + input.IpAddressType = awstypes.IpAddressType(v.(string)) } - _, err := conn.UpdateCustomRoutingAcceleratorWithContext(ctx, input) + _, err := conn.UpdateCustomRoutingAccelerator(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Custom Routing Accelerator (%s): %s", d.Id(), err) } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", d.Id(), err) } } @@ -252,28 +254,28 @@ func resourceCustomRoutingAcceleratorUpdate(ctx context.Context, d *schema.Resou nInput.AcceleratorArn = aws.String(d.Id()) // To change flow logs bucket and prefix attributes while flows are enabled, first disable flow logs. - if aws.BoolValue(oInput.FlowLogsEnabled) && aws.BoolValue(nInput.FlowLogsEnabled) { + if aws.ToBool(oInput.FlowLogsEnabled) && aws.ToBool(nInput.FlowLogsEnabled) { oInput.FlowLogsEnabled = aws.Bool(false) - _, err := conn.UpdateCustomRoutingAcceleratorAttributesWithContext(ctx, oInput) + _, err := conn.UpdateCustomRoutingAcceleratorAttributes(ctx, oInput) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Custom Routing Accelerator (%s) attributes: %s", d.Id(), err) } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", d.Id(), err) } } - _, err := conn.UpdateCustomRoutingAcceleratorAttributesWithContext(ctx, nInput) + _, err := conn.UpdateCustomRoutingAcceleratorAttributes(ctx, nInput) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Global Accelerator Custom Routing Accelerator (%s) attributes: %s", d.Id(), err) } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", d.Id(), err) } } } @@ -284,16 +286,16 @@ func resourceCustomRoutingAcceleratorUpdate(ctx context.Context, d *schema.Resou func resourceCustomRoutingAcceleratorDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) input := &globalaccelerator.UpdateCustomRoutingAcceleratorInput{ AcceleratorArn: aws.String(d.Id()), Enabled: aws.Bool(false), } - _, err := conn.UpdateCustomRoutingAcceleratorWithContext(ctx, input) + _, err := conn.UpdateCustomRoutingAccelerator(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return diags } @@ -302,15 +304,15 @@ func resourceCustomRoutingAcceleratorDelete(ctx context.Context, d *schema.Resou } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", d.Id(), err) } log.Printf("[DEBUG] Deleting Global Accelerator Custom Routing Accelerator (%s)", d.Id()) - _, err = conn.DeleteCustomRoutingAcceleratorWithContext(ctx, &globalaccelerator.DeleteCustomRoutingAcceleratorInput{ + _, err = conn.DeleteCustomRoutingAccelerator(ctx, &globalaccelerator.DeleteCustomRoutingAcceleratorInput{ AcceleratorArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return diags } @@ -321,18 +323,14 @@ func resourceCustomRoutingAcceleratorDelete(ctx context.Context, d *schema.Resou return diags } -func FindCustomRoutingAcceleratorByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.CustomRoutingAccelerator, error) { +func findCustomRoutingAcceleratorByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.CustomRoutingAccelerator, error) { input := &globalaccelerator.DescribeCustomRoutingAcceleratorInput{ AcceleratorArn: aws.String(arn), } - return findCustomRoutingAccelerator(ctx, conn, input) -} + output, err := conn.DescribeCustomRoutingAccelerator(ctx, input) -func findCustomRoutingAccelerator(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeCustomRoutingAcceleratorInput) (*globalaccelerator.CustomRoutingAccelerator, error) { - output, err := conn.DescribeCustomRoutingAcceleratorWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -350,18 +348,14 @@ func findCustomRoutingAccelerator(ctx context.Context, conn *globalaccelerator.G return output.Accelerator, nil } -func FindCustomRoutingAcceleratorAttributesByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.CustomRoutingAcceleratorAttributes, error) { +func findCustomRoutingAcceleratorAttributesByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.CustomRoutingAcceleratorAttributes, error) { input := &globalaccelerator.DescribeCustomRoutingAcceleratorAttributesInput{ AcceleratorArn: aws.String(arn), } - return findCustomRoutingAcceleratorAttributes(ctx, conn, input) -} - -func findCustomRoutingAcceleratorAttributes(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeCustomRoutingAcceleratorAttributesInput) (*globalaccelerator.CustomRoutingAcceleratorAttributes, error) { - output, err := conn.DescribeCustomRoutingAcceleratorAttributesWithContext(ctx, input) + output, err := conn.DescribeCustomRoutingAcceleratorAttributes(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAcceleratorNotFoundException) { + if errs.IsA[*awstypes.AcceleratorNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -379,9 +373,9 @@ func findCustomRoutingAcceleratorAttributes(ctx context.Context, conn *globalacc return output.AcceleratorAttributes, nil } -func statusCustomRoutingAccelerator(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) retry.StateRefreshFunc { +func statusCustomRoutingAccelerator(ctx context.Context, conn *globalaccelerator.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - accelerator, err := FindCustomRoutingAcceleratorByARN(ctx, conn, arn) + accelerator, err := findCustomRoutingAcceleratorByARN(ctx, conn, arn) if tfresource.NotFound(err) { return nil, "", nil @@ -391,21 +385,21 @@ func statusCustomRoutingAccelerator(ctx context.Context, conn *globalaccelerator return nil, "", err } - return accelerator, aws.StringValue(accelerator.Status), nil + return accelerator, string(accelerator.Status), nil } } -func waitCustomRoutingAcceleratorDeployed(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string, timeout time.Duration) (*globalaccelerator.CustomRoutingAccelerator, error) { //nolint:unparam +func waitCustomRoutingAcceleratorDeployed(ctx context.Context, conn *globalaccelerator.Client, arn string, timeout time.Duration) (*awstypes.CustomRoutingAccelerator, error) { //nolint:unparam stateConf := &retry.StateChangeConf{ - Pending: []string{globalaccelerator.AcceleratorStatusInProgress}, - Target: []string{globalaccelerator.AcceleratorStatusDeployed}, + Pending: enum.Slice(awstypes.AcceleratorStatusInProgress), + Target: enum.Slice(awstypes.AcceleratorStatusDeployed), Refresh: statusCustomRoutingAccelerator(ctx, conn, arn), Timeout: timeout, } outputRaw, err := stateConf.WaitForStateContext(ctx) - if output, ok := outputRaw.(*globalaccelerator.CustomRoutingAccelerator); ok { + if output, ok := outputRaw.(*awstypes.CustomRoutingAccelerator); ok { return output, err } @@ -416,6 +410,6 @@ func expandUpdateCustomRoutingAcceleratorAttributesInput(tfMap map[string]interf return (*globalaccelerator.UpdateCustomRoutingAcceleratorAttributesInput)(expandUpdateAcceleratorAttributesInput(tfMap)) } -func flattenCustomRoutingAcceleratorAttributes(apiObject *globalaccelerator.CustomRoutingAcceleratorAttributes) map[string]interface{} { - return flattenAcceleratorAttributes((*globalaccelerator.AcceleratorAttributes)(apiObject)) +func flattenCustomRoutingAcceleratorAttributes(apiObject *awstypes.CustomRoutingAcceleratorAttributes) map[string]interface{} { + return flattenAcceleratorAttributes((*awstypes.AcceleratorAttributes)(apiObject)) } diff --git a/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go b/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go index 4a10c5ef5a0..d0901a3defa 100644 --- a/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go +++ b/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go @@ -140,7 +140,7 @@ func dataSourceCustomRoutingAcceleratorRead(ctx context.Context, d *schema.Resou } d.Set("name", accelerator.Name) - acceleratorAttributes, err := FindCustomRoutingAcceleratorAttributesByARN(ctx, conn, d.Id()) + acceleratorAttributes, err := findCustomRoutingAcceleratorAttributesByARN(ctx, conn, d.Id()) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Custom Routing Accelerator (%s) attributes: %s", d.Id(), err) diff --git a/internal/service/globalaccelerator/custom_routing_accelerator_test.go b/internal/service/globalaccelerator/custom_routing_accelerator_test.go index 845f39f5612..dff9a140613 100644 --- a/internal/service/globalaccelerator/custom_routing_accelerator_test.go +++ b/internal/service/globalaccelerator/custom_routing_accelerator_test.go @@ -168,16 +168,12 @@ func TestAccGlobalAcceleratorCustomRoutingAccelerator_update(t *testing.T) { func testAccCheckCustomRoutingAcceleratorExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Global Accelerator Custom Routing Accelerator ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) _, err := tfglobalaccelerator.FindCustomRoutingAcceleratorByARN(ctx, conn, rs.Primary.ID) @@ -187,7 +183,7 @@ func testAccCheckCustomRoutingAcceleratorExists(ctx context.Context, n string) r func testAccCheckCustomRoutingAcceleratorDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_globalaccelerator_custom_routing_accelerator" { diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index 56e06b25568..0581232fc16 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -5,14 +5,16 @@ package globalaccelerator // Exports for use in tests only. var ( - ResourceAccelerator = resourceAccelerator - ResourceCrossAccountAttachment = newCrossAccountAttachmentResource - ResourceCustomRoutingListener = resourceCustomRoutingListener - ResourceEndpointGroup = resourceEndpointGroup - ResourceListener = resourceListener + ResourceAccelerator = resourceAccelerator + ResourceCrossAccountAttachment = newCrossAccountAttachmentResource + ResourceCustomRoutingAccelerator = resourceCustomRoutingAccelerator + ResourceCustomRoutingListener = resourceCustomRoutingListener + ResourceEndpointGroup = resourceEndpointGroup + ResourceListener = resourceListener - FindAcceleratorByARN = findAcceleratorByARN - FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN - FindCustomRoutingListenerByARN = findCustomRoutingListenerByARN - FindListenerByARN = findListenerByARN + FindAcceleratorByARN = findAcceleratorByARN + FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN + FindCustomRoutingAcceleratorByARN = findCustomRoutingAcceleratorByARN + FindCustomRoutingListenerByARN = findCustomRoutingListenerByARN + FindListenerByARN = findListenerByARN ) diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index 412e8c2c0f3..d58c7963b61 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -53,7 +53,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceCustomRoutingAccelerator, + Factory: resourceCustomRoutingAccelerator, TypeName: "aws_globalaccelerator_custom_routing_accelerator", Name: "Custom Routing Accelerator", Tags: &types.ServicePackageResourceTags{ From e88cd40f3b239926415edca979679d561ba89e05 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 15:38:14 -0400 Subject: [PATCH 30/35] d/aws_globalaccelerator_custom_routing_accelerator: Migrate to AWS SDK for GO v2. --- .../custom_routing_accelerator_data_source.go | 41 ++++++++----------- .../globalaccelerator/service_package_gen.go | 3 +- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go b/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go index d0901a3defa..7d22888cf8c 100644 --- a/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go +++ b/internal/service/globalaccelerator/custom_routing_accelerator_data_source.go @@ -6,8 +6,9 @@ package globalaccelerator import ( "context" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" "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" @@ -15,8 +16,8 @@ import ( tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" ) -// @SDKDataSource("aws_globalaccelerator_custom_routing_accelerator") -func DataSourceCustomRoutingAccelerator() *schema.Resource { +// @SDKDataSource("aws_globalaccelerator_custom_routing_accelerator", name="Custom Routing Accelerator") +func dataSourceCustomRoutingAccelerator() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceCustomRoutingAcceleratorRead, @@ -91,37 +92,29 @@ func DataSourceCustomRoutingAccelerator() *schema.Resource { func dataSourceCustomRoutingAcceleratorRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig - var results []*globalaccelerator.CustomRoutingAccelerator + var results []awstypes.CustomRoutingAccelerator + pages := globalaccelerator.NewListCustomRoutingAcceleratorsPaginator(conn, &globalaccelerator.ListCustomRoutingAcceleratorsInput{}) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) - err := conn.ListCustomRoutingAcceleratorsPagesWithContext(ctx, &globalaccelerator.ListCustomRoutingAcceleratorsInput{}, func(page *globalaccelerator.ListCustomRoutingAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + if err != nil { + return sdkdiag.AppendErrorf(diags, "listing Global Accelerator Custom Routing Accelerators: %s", err) } - for _, l := range page.Accelerators { - if l == nil { + for _, accelerator := range page.Accelerators { + if v, ok := d.GetOk("arn"); ok && v.(string) != aws.ToString(accelerator.AcceleratorArn) { continue } - if v, ok := d.GetOk("arn"); ok && v.(string) != aws.StringValue(l.AcceleratorArn) { + if v, ok := d.GetOk("name"); ok && v.(string) != aws.ToString(accelerator.Name) { continue } - if v, ok := d.GetOk("name"); ok && v.(string) != aws.StringValue(l.Name) { - continue - } - - results = append(results, l) + results = append(results, accelerator) } - - return !lastPage - }) - - if err != nil { - return sdkdiag.AppendErrorf(diags, "listing Global Accelerator Custom Routing Accelerators: %s", err) } if count := len(results); count != 1 { @@ -129,7 +122,7 @@ func dataSourceCustomRoutingAcceleratorRead(ctx context.Context, d *schema.Resou } accelerator := results[0] - d.SetId(aws.StringValue(accelerator.AcceleratorArn)) + d.SetId(aws.ToString(accelerator.AcceleratorArn)) d.Set("arn", accelerator.AcceleratorArn) d.Set("dns_name", accelerator.DnsName) d.Set("enabled", accelerator.Enabled) diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index d58c7963b61..c5e8f072e0a 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -36,8 +36,9 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { return []*types.ServicePackageSDKDataSource{ { - Factory: DataSourceCustomRoutingAccelerator, + Factory: dataSourceCustomRoutingAccelerator, TypeName: "aws_globalaccelerator_custom_routing_accelerator", + Name: "Custom Routing Accelerator", }, } } From 5f40b12698dc8a0127c68141a569ecef6ec7c622 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 16:09:13 -0400 Subject: [PATCH 31/35] r/aws_globalaccelerator_custom_routing_endpoint_group: Migrate to AWS SDK for GO v2. --- .../custom_routing_endpoint_group.go | 109 ++++++++---------- .../custom_routing_endpoint_group_test.go | 20 ++-- .../service/globalaccelerator/exports_test.go | 24 ++-- .../globalaccelerator/service_package_gen.go | 3 +- 4 files changed, 71 insertions(+), 85 deletions(-) diff --git a/internal/service/globalaccelerator/custom_routing_endpoint_group.go b/internal/service/globalaccelerator/custom_routing_endpoint_group.go index a0789b36996..ab59747d2b3 100644 --- a/internal/service/globalaccelerator/custom_routing_endpoint_group.go +++ b/internal/service/globalaccelerator/custom_routing_endpoint_group.go @@ -8,23 +8,25 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "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/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/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" "github.com/hashicorp/terraform-provider-aws/internal/flex" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) -// @SDKResource("aws_globalaccelerator_custom_routing_endpoint_group") -func ResourceCustomRoutingEndpointGroup() *schema.Resource { +// @SDKResource("aws_globalaccelerator_custom_routing_endpoint_group", name="Custom Routing Endpoint Group") +func resourceCustomRoutingEndpointGroup() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceCustomRoutingEndpointGroupCreate, ReadWithoutTimeout: resourceCustomRoutingEndpointGroupRead, @@ -59,8 +61,8 @@ func ResourceCustomRoutingEndpointGroup() *schema.Resource { Type: schema.TypeSet, Required: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice(globalaccelerator.CustomRoutingProtocol_Values(), false), + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.CustomRoutingProtocol](), }, }, "to_port": { @@ -104,7 +106,7 @@ func ResourceCustomRoutingEndpointGroup() *schema.Resource { func resourceCustomRoutingEndpointGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) input := &globalaccelerator.CreateCustomRoutingEndpointGroupInput{ DestinationConfigurations: expandCustomRoutingDestinationConfigurations(d.Get("destination_configuration").(*schema.Set).List()), @@ -117,38 +119,37 @@ func resourceCustomRoutingEndpointGroupCreate(ctx context.Context, d *schema.Res input.EndpointGroupRegion = aws.String(v.(string)) } - output, err := conn.CreateCustomRoutingEndpointGroupWithContext(ctx, input) + output, err := conn.CreateCustomRoutingEndpointGroup(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Global Accelerator Custom Routing Endpoint Group: %s", err) } - d.SetId(aws.StringValue(output.EndpointGroup.EndpointGroupArn)) + d.SetId(aws.ToString(output.EndpointGroup.EndpointGroupArn)) acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", acceleratorARN, err) } if v, ok := d.GetOk("endpoint_configuration"); ok { input := &globalaccelerator.AddCustomRoutingEndpointsInput{ - EndpointGroupArn: aws.String(d.Id()), EndpointConfigurations: expandCustomRoutingEndpointConfigurations(v.(*schema.Set).List()), + EndpointGroupArn: aws.String(d.Id()), } - _, err := conn.AddCustomRoutingEndpointsWithContext(ctx, input) + _, err := conn.AddCustomRoutingEndpoints(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "adding Global Accelerator Custom Routing Endpoint Group (%s) endpoints: %s", d.Id(), err) } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", acceleratorARN, err) } } @@ -157,9 +158,9 @@ func resourceCustomRoutingEndpointGroupCreate(ctx context.Context, d *schema.Res func resourceCustomRoutingEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - endpointGroup, err := FindCustomRoutingEndpointGroupByARN(ctx, conn, d.Id()) + endpointGroup, err := findCustomRoutingEndpointGroupByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Global Accelerator Custom Routing Endpoint Group (%s) not found, removing from state", d.Id()) @@ -172,7 +173,6 @@ func resourceCustomRoutingEndpointGroupRead(ctx context.Context, d *schema.Resou } listenerARN, err := endpointGroupARNToListenerARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -192,14 +192,14 @@ func resourceCustomRoutingEndpointGroupRead(ctx context.Context, d *schema.Resou func resourceCustomRoutingEndpointGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) log.Printf("[DEBUG] Deleting Global Accelerator Custom Routing Endpoint Group (%s)", d.Id()) - _, err := conn.DeleteCustomRoutingEndpointGroupWithContext(ctx, &globalaccelerator.DeleteCustomRoutingEndpointGroupInput{ + _, err := conn.DeleteCustomRoutingEndpointGroup(ctx, &globalaccelerator.DeleteCustomRoutingEndpointGroupInput{ EndpointGroupArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeEndpointGroupNotFoundException) { + if errs.IsA[*awstypes.EndpointGroupNotFoundException](err) { return diags } @@ -208,30 +208,25 @@ func resourceCustomRoutingEndpointGroupDelete(ctx context.Context, d *schema.Res } acceleratorARN, err := listenerOrEndpointGroupARNToAcceleratorARN(d.Id()) - if err != nil { return sdkdiag.AppendFromErr(diags, err) } if _, err := waitCustomRoutingAcceleratorDeployed(ctx, conn, acceleratorARN, d.Timeout(schema.TimeoutDelete)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deployment: %s", acceleratorARN, err) + return sdkdiag.AppendErrorf(diags, "waiting for Global Accelerator Custom Routing Accelerator (%s) deploy: %s", acceleratorARN, err) } return diags } -func FindCustomRoutingEndpointGroupByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.CustomRoutingEndpointGroup, error) { +func findCustomRoutingEndpointGroupByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.CustomRoutingEndpointGroup, error) { input := &globalaccelerator.DescribeCustomRoutingEndpointGroupInput{ EndpointGroupArn: aws.String(arn), } - return findCustomRoutingEndpointGroup(ctx, conn, input) -} - -func findCustomRoutingEndpointGroup(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeCustomRoutingEndpointGroupInput) (*globalaccelerator.CustomRoutingEndpointGroup, error) { - output, err := conn.DescribeCustomRoutingEndpointGroupWithContext(ctx, input) + output, err := conn.DescribeCustomRoutingEndpointGroup(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeEndpointGroupNotFoundException) { + if errs.IsA[*awstypes.EndpointGroupNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -249,34 +244,34 @@ func findCustomRoutingEndpointGroup(ctx context.Context, conn *globalaccelerator return output.EndpointGroup, nil } -func expandCustomRoutingEndpointDestinationConfiguration(tfMap map[string]interface{}) *globalaccelerator.CustomRoutingDestinationConfiguration { +func expandCustomRoutingEndpointDestinationConfiguration(tfMap map[string]interface{}) *awstypes.CustomRoutingDestinationConfiguration { if tfMap == nil { return nil } - apiObject := &globalaccelerator.CustomRoutingDestinationConfiguration{} + apiObject := &awstypes.CustomRoutingDestinationConfiguration{} if v, ok := tfMap["from_port"].(int); ok && v != 0 { - apiObject.FromPort = aws.Int64(int64(v)) + apiObject.FromPort = aws.Int32(int32(v)) } if v, ok := tfMap["protocols"].(*schema.Set); ok { - apiObject.Protocols = flex.ExpandStringSet(v) + apiObject.Protocols = flex.ExpandStringyValueSet[awstypes.CustomRoutingProtocol](v) } if v, ok := tfMap["to_port"].(int); ok && v != 0 { - apiObject.ToPort = aws.Int64(int64(v)) + apiObject.ToPort = aws.Int32(int32(v)) } return apiObject } -func expandCustomRoutingDestinationConfigurations(tfList []interface{}) []*globalaccelerator.CustomRoutingDestinationConfiguration { +func expandCustomRoutingDestinationConfigurations(tfList []interface{}) []awstypes.CustomRoutingDestinationConfiguration { if len(tfList) == 0 { return nil } - var apiObjects []*globalaccelerator.CustomRoutingDestinationConfiguration + var apiObjects []awstypes.CustomRoutingDestinationConfiguration for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) @@ -291,18 +286,18 @@ func expandCustomRoutingDestinationConfigurations(tfList []interface{}) []*globa continue } - apiObjects = append(apiObjects, apiObject) + apiObjects = append(apiObjects, *apiObject) } return apiObjects } -func expandCustomRoutingEndpointConfiguration(tfMap map[string]interface{}) *globalaccelerator.CustomRoutingEndpointConfiguration { +func expandCustomRoutingEndpointConfiguration(tfMap map[string]interface{}) *awstypes.CustomRoutingEndpointConfiguration { if tfMap == nil { return nil } - apiObject := &globalaccelerator.CustomRoutingEndpointConfiguration{} + apiObject := &awstypes.CustomRoutingEndpointConfiguration{} if v, ok := tfMap["endpoint_id"].(string); ok && v != "" { apiObject.EndpointId = aws.String(v) @@ -311,12 +306,12 @@ func expandCustomRoutingEndpointConfiguration(tfMap map[string]interface{}) *glo return apiObject } -func expandCustomRoutingEndpointConfigurations(tfList []interface{}) []*globalaccelerator.CustomRoutingEndpointConfiguration { +func expandCustomRoutingEndpointConfigurations(tfList []interface{}) []awstypes.CustomRoutingEndpointConfiguration { if len(tfList) == 0 { return nil } - var apiObjects []*globalaccelerator.CustomRoutingEndpointConfiguration + var apiObjects []awstypes.CustomRoutingEndpointConfiguration for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) @@ -331,13 +326,13 @@ func expandCustomRoutingEndpointConfigurations(tfList []interface{}) []*globalac continue } - apiObjects = append(apiObjects, apiObject) + apiObjects = append(apiObjects, *apiObject) } return apiObjects } -func flattenCustomRoutingDestinationDescription(apiObject *globalaccelerator.CustomRoutingDestinationDescription) map[string]interface{} { +func flattenCustomRoutingDestinationDescription(apiObject *awstypes.CustomRoutingDestinationDescription) map[string]interface{} { if apiObject == nil { return nil } @@ -345,21 +340,21 @@ func flattenCustomRoutingDestinationDescription(apiObject *globalaccelerator.Cus tfMap := map[string]interface{}{} if v := apiObject.FromPort; v != nil { - tfMap["from_port"] = aws.Int64Value(v) + tfMap["from_port"] = aws.ToInt32(v) } if v := apiObject.Protocols; v != nil { - tfMap["protocols"] = aws.StringValueSlice(v) + tfMap["protocols"] = v } if v := apiObject.ToPort; v != nil { - tfMap["to_port"] = aws.Int64Value(v) + tfMap["to_port"] = aws.ToInt32(v) } return tfMap } -func flattenCustomRoutingDestinationDescriptions(apiObjects []*globalaccelerator.CustomRoutingDestinationDescription) []interface{} { +func flattenCustomRoutingDestinationDescriptions(apiObjects []awstypes.CustomRoutingDestinationDescription) []interface{} { if len(apiObjects) == 0 { return nil } @@ -367,17 +362,13 @@ func flattenCustomRoutingDestinationDescriptions(apiObjects []*globalaccelerator var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenCustomRoutingDestinationDescription(apiObject)) + tfList = append(tfList, flattenCustomRoutingDestinationDescription(&apiObject)) } return tfList } -func flattenCustomRoutingEndpointDescription(apiObject *globalaccelerator.CustomRoutingEndpointDescription) map[string]interface{} { +func flattenCustomRoutingEndpointDescription(apiObject *awstypes.CustomRoutingEndpointDescription) map[string]interface{} { if apiObject == nil { return nil } @@ -385,13 +376,13 @@ func flattenCustomRoutingEndpointDescription(apiObject *globalaccelerator.Custom tfMap := map[string]interface{}{} if v := apiObject.EndpointId; v != nil { - tfMap["endpoint_id"] = aws.StringValue(v) + tfMap["endpoint_id"] = aws.ToString(v) } return tfMap } -func flattenCustomRoutingEndpointDescriptions(apiObjects []*globalaccelerator.CustomRoutingEndpointDescription) []interface{} { +func flattenCustomRoutingEndpointDescriptions(apiObjects []awstypes.CustomRoutingEndpointDescription) []interface{} { if len(apiObjects) == 0 { return nil } @@ -399,11 +390,7 @@ func flattenCustomRoutingEndpointDescriptions(apiObjects []*globalaccelerator.Cu var tfList []interface{} for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } - - tfList = append(tfList, flattenCustomRoutingEndpointDescription(apiObject)) + tfList = append(tfList, flattenCustomRoutingEndpointDescription(&apiObject)) } return tfList diff --git a/internal/service/globalaccelerator/custom_routing_endpoint_group_test.go b/internal/service/globalaccelerator/custom_routing_endpoint_group_test.go index 2fcb3d9bc74..6e3aaf43d73 100644 --- a/internal/service/globalaccelerator/custom_routing_endpoint_group_test.go +++ b/internal/service/globalaccelerator/custom_routing_endpoint_group_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/service/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -21,7 +21,7 @@ import ( func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_basic(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.CustomRoutingEndpointGroup + var v awstypes.CustomRoutingEndpointGroup resourceName := "aws_globalaccelerator_custom_routing_endpoint_group.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -56,7 +56,7 @@ func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_basic(t *testing.T) { func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_disappears(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.CustomRoutingEndpointGroup + var v awstypes.CustomRoutingEndpointGroup resourceName := "aws_globalaccelerator_custom_routing_endpoint_group.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -80,7 +80,7 @@ func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_disappears(t *testing.T) func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_endpointConfiguration(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.CustomRoutingEndpointGroup + var v awstypes.CustomRoutingEndpointGroup resourceName := "aws_globalaccelerator_custom_routing_endpoint_group.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -116,7 +116,7 @@ func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_endpointConfiguration(t func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_endpointGroupRegion(t *testing.T) { ctx := acctest.Context(t) - var v globalaccelerator.CustomRoutingEndpointGroup + var v awstypes.CustomRoutingEndpointGroup resourceName := "aws_globalaccelerator_custom_routing_endpoint_group.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -149,18 +149,14 @@ func TestAccGlobalAcceleratorCustomRoutingEndpointGroup_endpointGroupRegion(t *t }) } -func testAccCheckCustomRoutingEndpointGroupExists(ctx context.Context, n string, v *globalaccelerator.CustomRoutingEndpointGroup) resource.TestCheckFunc { +func testAccCheckCustomRoutingEndpointGroupExists(ctx context.Context, n string, v *awstypes.CustomRoutingEndpointGroup) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) - rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No Global Accelerator Custom Routing Endpoint Group ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) output, err := tfglobalaccelerator.FindCustomRoutingEndpointGroupByARN(ctx, conn, rs.Primary.ID) @@ -176,7 +172,7 @@ func testAccCheckCustomRoutingEndpointGroupExists(ctx context.Context, n string, func testAccCheckCustomRoutingEndpointGroupDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_globalaccelerator_custom_routing_endpoint_group" { diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index 0581232fc16..4eb813d91aa 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -5,16 +5,18 @@ package globalaccelerator // Exports for use in tests only. var ( - ResourceAccelerator = resourceAccelerator - ResourceCrossAccountAttachment = newCrossAccountAttachmentResource - ResourceCustomRoutingAccelerator = resourceCustomRoutingAccelerator - ResourceCustomRoutingListener = resourceCustomRoutingListener - ResourceEndpointGroup = resourceEndpointGroup - ResourceListener = resourceListener + ResourceAccelerator = resourceAccelerator + ResourceCrossAccountAttachment = newCrossAccountAttachmentResource + ResourceCustomRoutingAccelerator = resourceCustomRoutingAccelerator + ResourceCustomRoutingEndpointGroup = resourceCustomRoutingEndpointGroup + ResourceCustomRoutingListener = resourceCustomRoutingListener + ResourceEndpointGroup = resourceEndpointGroup + ResourceListener = resourceListener - FindAcceleratorByARN = findAcceleratorByARN - FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN - FindCustomRoutingAcceleratorByARN = findCustomRoutingAcceleratorByARN - FindCustomRoutingListenerByARN = findCustomRoutingListenerByARN - FindListenerByARN = findListenerByARN + FindAcceleratorByARN = findAcceleratorByARN + FindCrossAccountAttachmentByARN = findCrossAccountAttachmentByARN + FindCustomRoutingAcceleratorByARN = findCustomRoutingAcceleratorByARN + FindCustomRoutingEndpointGroupByARN = findCustomRoutingEndpointGroupByARN + FindCustomRoutingListenerByARN = findCustomRoutingListenerByARN + FindListenerByARN = findListenerByARN ) diff --git a/internal/service/globalaccelerator/service_package_gen.go b/internal/service/globalaccelerator/service_package_gen.go index c5e8f072e0a..f94220966ad 100644 --- a/internal/service/globalaccelerator/service_package_gen.go +++ b/internal/service/globalaccelerator/service_package_gen.go @@ -62,8 +62,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceCustomRoutingEndpointGroup, + Factory: resourceCustomRoutingEndpointGroup, TypeName: "aws_globalaccelerator_custom_routing_endpoint_group", + Name: "Custom Routing Endpoint Group", }, { Factory: resourceCustomRoutingListener, From 13e92cef0038f4e682b35ec74c1d03b16ef5a90a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 16:15:04 -0400 Subject: [PATCH 32/35] r/aws_globalaccelerator_cross_account_attachment: Migrate to AWS SDK for GO v2. --- .../cross_account_attachment.go | 43 +++++++++---------- .../cross_account_attachment_test.go | 16 +++---- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/internal/service/globalaccelerator/cross_account_attachment.go b/internal/service/globalaccelerator/cross_account_attachment.go index 39cf5ee950d..5bc7b2eaa41 100644 --- a/internal/service/globalaccelerator/cross_account_attachment.go +++ b/internal/service/globalaccelerator/cross_account_attachment.go @@ -7,9 +7,9 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - "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/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "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/flex" "github.com/hashicorp/terraform-provider-aws/internal/framework" @@ -98,7 +99,7 @@ func (r *crossAccountAttachmentResource) Create(ctx context.Context, request res return } - conn := r.Meta().GlobalAcceleratorConn(ctx) + conn := r.Meta().GlobalAcceleratorClient(ctx) input := &globalaccelerator.CreateCrossAccountAttachmentInput{} response.Diagnostics.Append(fwflex.Expand(ctx, data, input)...) @@ -109,7 +110,7 @@ func (r *crossAccountAttachmentResource) Create(ctx context.Context, request res input.IdempotencyToken = aws.String(id.UniqueId()) input.Tags = getTagsIn(ctx) - output, err := conn.CreateCrossAccountAttachmentWithContext(ctx, input) + output, err := conn.CreateCrossAccountAttachment(ctx, input) if err != nil { response.Diagnostics.AddError("creating Global Accelerator Cross-account Attachment", err.Error()) @@ -139,7 +140,7 @@ func (r *crossAccountAttachmentResource) Read(ctx context.Context, request resou return } - conn := r.Meta().GlobalAcceleratorConn(ctx) + conn := r.Meta().GlobalAcceleratorClient(ctx) output, err := findCrossAccountAttachmentByARN(ctx, conn, data.ID.ValueString()) @@ -180,7 +181,7 @@ func (r *crossAccountAttachmentResource) Update(ctx context.Context, request res return } - conn := r.Meta().GlobalAcceleratorConn(ctx) + conn := r.Meta().GlobalAcceleratorClient(ctx) if !new.Name.Equal(old.Name) || !new.Principals.Equal(old.Principals) || @@ -195,7 +196,7 @@ func (r *crossAccountAttachmentResource) Update(ctx context.Context, request res if !new.Principals.Equal(old.Principals) { oldPrincipals, newPrincipals := fwflex.ExpandFrameworkStringValueSet(ctx, old.Principals), fwflex.ExpandFrameworkStringValueSet(ctx, new.Principals) - input.AddPrincipals, input.RemovePrincipals = aws.StringSlice(newPrincipals.Difference(oldPrincipals)), aws.StringSlice(oldPrincipals.Difference(newPrincipals)) + input.AddPrincipals, input.RemovePrincipals = newPrincipals.Difference(oldPrincipals), oldPrincipals.Difference(newPrincipals) } if !new.Resources.Equal(old.Resources) { @@ -215,21 +216,21 @@ func (r *crossAccountAttachmentResource) Update(ctx context.Context, request res return v1.EndpointID.Equal(v2.EndpointID) && v1.Region.Equal(v2.Region) }) - input.AddResources = tfslices.ApplyToAll(add, func(v *resourceModel) *globalaccelerator.Resource { - return &globalaccelerator.Resource{ + input.AddResources = tfslices.ApplyToAll(add, func(v *resourceModel) awstypes.Resource { + return awstypes.Resource{ EndpointId: fwflex.StringFromFramework(ctx, v.EndpointID), Region: fwflex.StringFromFramework(ctx, v.Region), } }) - input.RemoveResources = tfslices.ApplyToAll(remove, func(v *resourceModel) *globalaccelerator.Resource { - return &globalaccelerator.Resource{ + input.RemoveResources = tfslices.ApplyToAll(remove, func(v *resourceModel) awstypes.Resource { + return awstypes.Resource{ EndpointId: fwflex.StringFromFramework(ctx, v.EndpointID), Region: fwflex.StringFromFramework(ctx, v.Region), } }) } - output, err := conn.UpdateCrossAccountAttachmentWithContext(ctx, input) + output, err := conn.UpdateCrossAccountAttachment(ctx, input) if err != nil { response.Diagnostics.AddError(fmt.Sprintf("updating Global Accelerator Cross-account Attachment (%s)", new.ID.ValueString()), err.Error()) @@ -252,13 +253,13 @@ func (r *crossAccountAttachmentResource) Delete(ctx context.Context, request res return } - conn := r.Meta().GlobalAcceleratorConn(ctx) + conn := r.Meta().GlobalAcceleratorClient(ctx) - _, err := conn.DeleteCrossAccountAttachmentWithContext(ctx, &globalaccelerator.DeleteCrossAccountAttachmentInput{ + _, err := conn.DeleteCrossAccountAttachment(ctx, &globalaccelerator.DeleteCrossAccountAttachmentInput{ AttachmentArn: fwflex.StringFromFramework(ctx, data.ID), }) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAttachmentNotFoundException) { + if errs.IsA[*awstypes.AttachmentNotFoundException](err) { return } @@ -273,18 +274,14 @@ func (r *crossAccountAttachmentResource) ModifyPlan(ctx context.Context, request r.SetTagsAll(ctx, request, response) } -func findCrossAccountAttachmentByARN(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, arn string) (*globalaccelerator.Attachment, error) { +func findCrossAccountAttachmentByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.Attachment, error) { input := &globalaccelerator.DescribeCrossAccountAttachmentInput{ AttachmentArn: aws.String(arn), } - return findCrossAccountAttachment(ctx, conn, input) -} - -func findCrossAccountAttachment(ctx context.Context, conn *globalaccelerator.GlobalAccelerator, input *globalaccelerator.DescribeCrossAccountAttachmentInput) (*globalaccelerator.Attachment, error) { - output, err := conn.DescribeCrossAccountAttachmentWithContext(ctx, input) + output, err := conn.DescribeCrossAccountAttachment(ctx, input) - if tfawserr.ErrCodeEquals(err, globalaccelerator.ErrCodeAttachmentNotFoundException) { + if errs.IsA[*awstypes.AttachmentNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, diff --git a/internal/service/globalaccelerator/cross_account_attachment_test.go b/internal/service/globalaccelerator/cross_account_attachment_test.go index 63840f72cf5..2b01ae97178 100644 --- a/internal/service/globalaccelerator/cross_account_attachment_test.go +++ b/internal/service/globalaccelerator/cross_account_attachment_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/service/globalaccelerator" + awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -24,7 +24,7 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_basic(t *testing.T) { resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var v globalaccelerator.Attachment + var v awstypes.Attachment resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, @@ -66,7 +66,7 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_principals(t *testing.T) { rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) rAccountID1 := sdkacctest.RandStringFromCharSet(12, "012346789") rAccountID2 := sdkacctest.RandStringFromCharSet(12, "012346789") - var v globalaccelerator.Attachment + var v awstypes.Attachment resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, @@ -135,7 +135,7 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_disappears(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var v globalaccelerator.Attachment + var v awstypes.Attachment resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, @@ -159,7 +159,7 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_tags(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_globalaccelerator_cross_account_attachment.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - var v globalaccelerator.Attachment + var v awstypes.Attachment resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, @@ -204,7 +204,7 @@ func TestAccGlobalAcceleratorCrossAccountAttachment_tags(t *testing.T) { func testAccCheckCrossAccountAttachmentDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_globalaccelerator_cross_account_attachment" { @@ -228,14 +228,14 @@ func testAccCheckCrossAccountAttachmentDestroy(ctx context.Context) resource.Tes } } -func testAccCheckCrossAccountAttachmentExists(ctx context.Context, n string, v *globalaccelerator.Attachment) resource.TestCheckFunc { +func testAccCheckCrossAccountAttachmentExists(ctx context.Context, n string, v *awstypes.Attachment) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } - conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlobalAcceleratorClient(ctx) output, err := tfglobalaccelerator.FindCrossAccountAttachmentByARN(ctx, conn, rs.Primary.ID) From ee9e525b9602672001646087d443c3a99e81332c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 16:18:48 -0400 Subject: [PATCH 33/35] globalaccelerator: Some clean up. --- internal/service/globalaccelerator/arn.go | 16 ++++++++-------- .../service/globalaccelerator/endpoint_group.go | 4 ++-- .../service/globalaccelerator/exports_test.go | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/internal/service/globalaccelerator/arn.go b/internal/service/globalaccelerator/arn.go index a6db91eabf1..d842e5c2208 100644 --- a/internal/service/globalaccelerator/arn.go +++ b/internal/service/globalaccelerator/arn.go @@ -11,8 +11,8 @@ import ( ) const ( - ARNSeparator = "/" - ARNService = "globalaccelerator" + arnSeparator = "/" + arnService = "globalaccelerator" ) // endpointGroupARNToListenerARN converts an endpoint group ARN to a listener ARN. @@ -24,11 +24,11 @@ func endpointGroupARNToListenerARN(inputARN string) (string, error) { 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), 6; actual < expected { return "", fmt.Errorf("expected at least %d resource parts in ARN (%s), got: %d", expected, inputARN, actual) @@ -39,7 +39,7 @@ func endpointGroupARNToListenerARN(inputARN string) (string, error) { Service: parsedARN.Service, Region: parsedARN.Region, AccountID: parsedARN.AccountID, - Resource: strings.Join(resourceParts[0:4], ARNSeparator), + Resource: strings.Join(resourceParts[0:4], arnSeparator), }.String() return outputARN, nil @@ -54,11 +54,11 @@ func listenerOrEndpointGroupARNToAcceleratorARN(inputARN string) (string, error) 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 at least %d resource parts in ARN (%s), got: %d", expected, inputARN, actual) @@ -69,7 +69,7 @@ func listenerOrEndpointGroupARNToAcceleratorARN(inputARN string) (string, error) Service: parsedARN.Service, Region: parsedARN.Region, AccountID: parsedARN.AccountID, - Resource: strings.Join(resourceParts[0:2], ARNSeparator), + Resource: strings.Join(resourceParts[0:2], arnSeparator), }.String() return outputARN, nil diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index 5f8346f6391..271baf23c57 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -212,7 +212,7 @@ func resourceEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta var diags diag.Diagnostics conn := meta.(*conns.AWSClient).GlobalAcceleratorClient(ctx) - endpointGroup, err := FindEndpointGroupByARN(ctx, conn, d.Id()) + endpointGroup, err := findEndpointGroupByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Global Accelerator endpoint group (%s) not found, removing from state", d.Id()) @@ -339,7 +339,7 @@ func resourceEndpointGroupDelete(ctx context.Context, d *schema.ResourceData, me return diags } -func FindEndpointGroupByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.EndpointGroup, error) { +func findEndpointGroupByARN(ctx context.Context, conn *globalaccelerator.Client, arn string) (*awstypes.EndpointGroup, error) { input := &globalaccelerator.DescribeEndpointGroupInput{ EndpointGroupArn: aws.String(arn), } diff --git a/internal/service/globalaccelerator/exports_test.go b/internal/service/globalaccelerator/exports_test.go index 4eb813d91aa..2a5c6fee917 100644 --- a/internal/service/globalaccelerator/exports_test.go +++ b/internal/service/globalaccelerator/exports_test.go @@ -18,5 +18,6 @@ var ( FindCustomRoutingAcceleratorByARN = findCustomRoutingAcceleratorByARN FindCustomRoutingEndpointGroupByARN = findCustomRoutingEndpointGroupByARN FindCustomRoutingListenerByARN = findCustomRoutingListenerByARN + FindEndpointGroupByARN = findEndpointGroupByARN FindListenerByARN = findListenerByARN ) From 6aa0bbdc35c4a519d3244c018a3e95b35a3fde76 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 16:33:38 -0400 Subject: [PATCH 34/35] globalaccelerator: Migrate sweepers to AWS SDK for Go v2. --- internal/service/globalaccelerator/sweep.go | 327 ++++++++------------ 1 file changed, 131 insertions(+), 196 deletions(-) diff --git a/internal/service/globalaccelerator/sweep.go b/internal/service/globalaccelerator/sweep.go index 5a82f7406b0..a340596bb43 100644 --- a/internal/service/globalaccelerator/sweep.go +++ b/internal/service/globalaccelerator/sweep.go @@ -7,12 +7,11 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/globalaccelerator" - multierror "github.com/hashicorp/go-multierror" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" - "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv1" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" ) func RegisterSweepers() { @@ -65,33 +64,30 @@ func sweepAccelerators(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.GlobalAcceleratorConn(ctx) + conn := client.GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListAcceleratorsInput{} sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListAcceleratorsPagesWithContext(ctx, input, func(page *globalaccelerator.ListAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListAcceleratorsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Global Accelerator Accelerator sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing Global Accelerator Accelerators (%s): %w", region, err) } for _, v := range page.Accelerators { - r := ResourceAccelerator() + r := resourceAccelerator() d := r.Data(nil) - d.SetId(aws.StringValue(v.AcceleratorArn)) + d.SetId(aws.ToString(v.AcceleratorArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Global Accelerator Accelerator sweep for %s: %s", region, err) - return nil - } - - if err != nil { - return fmt.Errorf("error listing Global Accelerator Accelerators (%s): %w", region, err) } err = sweep.SweepOrchestrator(ctx, sweepResources) @@ -109,14 +105,21 @@ func sweepEndpointGroups(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.GlobalAcceleratorConn(ctx) + conn := client.GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListAcceleratorsInput{} - var sweeperErrs *multierror.Error sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListAcceleratorsPagesWithContext(ctx, input, func(page *globalaccelerator.ListAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListAcceleratorsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Global Accelerator Endpoint Group sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing Global Accelerator Accelerators (%s): %w", region, err) } for _, v := range page.Accelerators { @@ -124,9 +127,12 @@ func sweepEndpointGroups(region string) error { AcceleratorArn: v.AcceleratorArn, } - err := conn.ListListenersPagesWithContext(ctx, input, func(page *globalaccelerator.ListListenersOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListListenersPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + continue } for _, v := range page.Listeners { @@ -134,62 +140,34 @@ func sweepEndpointGroups(region string) error { ListenerArn: v.ListenerArn, } - err := conn.ListEndpointGroupsPagesWithContext(ctx, input, func(page *globalaccelerator.ListEndpointGroupsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListEndpointGroupsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + continue } for _, v := range page.EndpointGroups { - r := ResourceEndpointGroup() + r := resourceEndpointGroup() d := r.Data(nil) - d.SetId(aws.StringValue(v.EndpointGroupArn)) + d.SetId(aws.ToString(v.EndpointGroupArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - continue - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Endpoint Groups (%s): %w", region, err)) } } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - continue - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Listeners (%s): %w", region, err)) } } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Global Accelerator Endpoint Group sweep for %s: %s", region, err) - return sweeperErrs.ErrorOrNil() // In case we have completed some pages, but had errors - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Accelerators (%s): %w", region, err)) } err = sweep.SweepOrchestrator(ctx, sweepResources) if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error sweeping Global Accelerator Endpoint Groups (%s): %w", region, err)) + return fmt.Errorf("error sweeping Global Accelerator Endpoint Groups (%s): %w", region, err) } - return sweeperErrs.ErrorOrNil() + return nil } func sweepListeners(region string) error { @@ -198,14 +176,21 @@ func sweepListeners(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.GlobalAcceleratorConn(ctx) + conn := client.GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListAcceleratorsInput{} - var sweeperErrs *multierror.Error sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListAcceleratorsPagesWithContext(ctx, input, func(page *globalaccelerator.ListAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListAcceleratorsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Global Accelerator Endpoint Group sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing Global Accelerator Accelerators (%s): %w", region, err) } for _, v := range page.Accelerators { @@ -213,50 +198,32 @@ func sweepListeners(region string) error { AcceleratorArn: v.AcceleratorArn, } - err := conn.ListListenersPagesWithContext(ctx, input, func(page *globalaccelerator.ListListenersOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListListenersPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + continue } for _, v := range page.Listeners { - r := ResourceListener() + r := resourceListener() d := r.Data(nil) - d.SetId(aws.StringValue(v.ListenerArn)) + d.SetId(aws.ToString(v.ListenerArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - continue - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Listeners (%s): %w", region, err)) } } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Global Accelerator Listener sweep for %s: %s", region, err) - return sweeperErrs.ErrorOrNil() // In case we have completed some pages, but had errors - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Accelerators (%s): %w", region, err)) } err = sweep.SweepOrchestrator(ctx, sweepResources) if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error sweeping Global Accelerator Listeners (%s): %w", region, err)) + return fmt.Errorf("error sweeping Global Accelerator Listeners (%s): %w", region, err) } - return sweeperErrs.ErrorOrNil() + return nil } func sweepCustomRoutingAccelerators(region string) error { @@ -265,33 +232,30 @@ func sweepCustomRoutingAccelerators(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.GlobalAcceleratorConn(ctx) + conn := client.GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListCustomRoutingAcceleratorsInput{} sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListCustomRoutingAcceleratorsPagesWithContext(ctx, input, func(page *globalaccelerator.ListCustomRoutingAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListCustomRoutingAcceleratorsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Global Accelerator Custom Routing Accelerator sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing Global Accelerator Custom Routing Accelerators (%s): %w", region, err) } for _, v := range page.Accelerators { - r := ResourceCustomRoutingAccelerator() + r := resourceCustomRoutingAccelerator() d := r.Data(nil) - d.SetId(aws.StringValue(v.AcceleratorArn)) + d.SetId(aws.ToString(v.AcceleratorArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Global Accelerator Custom Routing Accelerator sweep for %s: %s", region, err) - return nil - } - - if err != nil { - return fmt.Errorf("error listing Global Accelerator Custom Routing Accelerators (%s): %w", region, err) } err = sweep.SweepOrchestrator(ctx, sweepResources) @@ -309,14 +273,21 @@ func sweepCustomRoutingEndpointGroups(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.GlobalAcceleratorConn(ctx) + conn := client.GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListCustomRoutingAcceleratorsInput{} - var sweeperErrs *multierror.Error sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListCustomRoutingAcceleratorsPagesWithContext(ctx, input, func(page *globalaccelerator.ListCustomRoutingAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListCustomRoutingAcceleratorsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Global Accelerator Custom Routing Accelerator sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing Global Accelerator Custom Routing Accelerators (%s): %w", region, err) } for _, v := range page.Accelerators { @@ -324,9 +295,12 @@ func sweepCustomRoutingEndpointGroups(region string) error { AcceleratorArn: v.AcceleratorArn, } - err := conn.ListCustomRoutingListenersPagesWithContext(ctx, input, func(page *globalaccelerator.ListCustomRoutingListenersOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListCustomRoutingListenersPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + continue } for _, v := range page.Listeners { @@ -334,62 +308,34 @@ func sweepCustomRoutingEndpointGroups(region string) error { ListenerArn: v.ListenerArn, } - err := conn.ListCustomRoutingEndpointGroupsPagesWithContext(ctx, input, func(page *globalaccelerator.ListCustomRoutingEndpointGroupsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListCustomRoutingEndpointGroupsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + continue } for _, v := range page.EndpointGroups { - r := ResourceCustomRoutingEndpointGroup() + r := resourceCustomRoutingEndpointGroup() d := r.Data(nil) - d.SetId(aws.StringValue(v.EndpointGroupArn)) + d.SetId(aws.ToString(v.EndpointGroupArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - continue - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Custom Routing Endpoint Groups (%s): %w", region, err)) } } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - continue - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Custom Routing Listeners (%s): %w", region, err)) } } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Global AcceleratorCustom Routing Endpoint Group sweep for %s: %s", region, err) - return sweeperErrs.ErrorOrNil() // In case we have completed some pages, but had errors - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Custom Routing Accelerators (%s): %w", region, err)) } err = sweep.SweepOrchestrator(ctx, sweepResources) if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error sweeping Global Accelerator Custom Routing Endpoint Groups (%s): %w", region, err)) + return fmt.Errorf("error sweeping Global Accelerator Custom Routing Endpoint Groups (%s): %w", region, err) } - return sweeperErrs.ErrorOrNil() + return nil } func sweepCustomRoutingListeners(region string) error { @@ -398,14 +344,21 @@ func sweepCustomRoutingListeners(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.GlobalAcceleratorConn(ctx) + conn := client.GlobalAcceleratorClient(ctx) input := &globalaccelerator.ListCustomRoutingAcceleratorsInput{} - var sweeperErrs *multierror.Error sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListCustomRoutingAcceleratorsPagesWithContext(ctx, input, func(page *globalaccelerator.ListCustomRoutingAcceleratorsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListCustomRoutingAcceleratorsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping Global Accelerator Custom Routing Accelerator sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing Global Accelerator Custom Routing Accelerators (%s): %w", region, err) } for _, v := range page.Accelerators { @@ -413,48 +366,30 @@ func sweepCustomRoutingListeners(region string) error { AcceleratorArn: v.AcceleratorArn, } - err := conn.ListCustomRoutingListenersPagesWithContext(ctx, input, func(page *globalaccelerator.ListCustomRoutingListenersOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := globalaccelerator.NewListCustomRoutingListenersPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + continue } for _, v := range page.Listeners { - r := ResourceCustomRoutingListener() + r := resourceCustomRoutingListener() d := r.Data(nil) - d.SetId(aws.StringValue(v.ListenerArn)) + d.SetId(aws.ToString(v.ListenerArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - continue - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Custom Routing Listeners (%s): %w", region, err)) } } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping Global Accelerator Custom Routing Listener sweep for %s: %s", region, err) - return sweeperErrs.ErrorOrNil() // In case we have completed some pages, but had errors - } - - if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error listing Global Accelerator Custom Routing Accelerators (%s): %w", region, err)) } err = sweep.SweepOrchestrator(ctx, sweepResources) if err != nil { - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error sweeping Global Accelerator Custom Routing Listeners (%s): %w", region, err)) + return fmt.Errorf("error sweeping Global Accelerator Custom Routing Listeners (%s): %w", region, err) } - return sweeperErrs.ErrorOrNil() + return nil } From 3577e156e120eb9307977db8dcbf1bc3eecd94f1 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 23 Apr 2024 16:45:31 -0400 Subject: [PATCH 35/35] globalaccelerator: Add 'NewClient'. --- .../globalaccelerator/service_package.go | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/internal/service/globalaccelerator/service_package.go b/internal/service/globalaccelerator/service_package.go index 4126e265623..f6ebfa80016 100644 --- a/internal/service/globalaccelerator/service_package.go +++ b/internal/service/globalaccelerator/service_package.go @@ -6,21 +6,21 @@ package globalaccelerator import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - globalaccelerator_sdkv1 "github.com/aws/aws-sdk-go/service/globalaccelerator" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" + "github.com/hashicorp/terraform-provider-aws/names" ) -// NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, m map[string]any) (*globalaccelerator_sdkv1.GlobalAccelerator, error) { - sess := m["session"].(*session_sdkv1.Session) - config := &aws_sdkv1.Config{Endpoint: aws_sdkv1.String(m["endpoint"].(string))} +// NewConn returns a new AWS SDK for Go v2 client for this service package's AWS API. +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*globalaccelerator.Client, error) { + cfg := *(config["aws_sdkv2_config"].(*aws.Config)) - // Force "global" services to correct Regions. - if m["partition"].(string) == endpoints_sdkv1.AwsPartitionID { - config.Region = aws_sdkv1.String(endpoints_sdkv1.UsWest2RegionID) - } - - return globalaccelerator_sdkv1.New(sess.Copy(config)), nil + return globalaccelerator.NewFromConfig(cfg, func(o *globalaccelerator.Options) { + if endpoint := config["endpoint"].(string); endpoint != "" { + o.BaseEndpoint = aws.String(endpoint) + } else if config["partition"].(string) == names.StandardPartitionID { + // Global Accelerator endpoint is only available in AWS Commercial us-west-2 Region. + o.Region = names.USWest2RegionID + } + }), nil }