From c80fa94098c36be35f0d66fae36d8ac2e8853171 Mon Sep 17 00:00:00 2001 From: Ryan Neal Date: Fri, 3 May 2024 15:00:05 -0600 Subject: [PATCH 1/9] add field for cross account support in endpoint groups for AGA --- .../globalaccelerator/endpoint_group.go | 9 +++ .../globalaccelerator/endpoint_group_test.go | 65 +++++++++++++++++++ ...alaccelerator_endpoint_group.html.markdown | 1 + ...alaccelerator_endpoint_group.html.markdown | 1 + 4 files changed, 76 insertions(+) diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index 754b8b766278..2f818a261f36 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -68,6 +68,11 @@ func resourceEndpointGroup() *schema.Resource { Optional: true, ValidateFunc: validation.IntBetween(0, 255), }, + "cross_account_attachment_arn": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, }, }, }, @@ -384,6 +389,10 @@ func expandEndpointConfiguration(tfMap map[string]interface{}) *awstypes.Endpoin apiObject.Weight = aws.Int32(int32(v)) } + if v, ok := tfMap["cross_account_attachment_arn"].(string); ok && v != "" { + apiObject.AttachmentArn = aws.String(v) + } + return apiObject } diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index d73c4b1ab74b..dca1ea8b8006 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -46,6 +46,46 @@ func TestAccGlobalAcceleratorEndpointGroup_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "health_check_path", ""), resource.TestCheckResourceAttr(resourceName, "health_check_port", "80"), resource.TestCheckResourceAttr(resourceName, "health_check_protocol", "TCP"), + resource.TestCheckResourceAttr(resourceName, "cross_account_attachment_arn", ""), + acctest.MatchResourceAttrGlobalARN(resourceName, "listener_arn", "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+`)), + resource.TestCheckResourceAttr(resourceName, "port_override.#", "0"), + resource.TestCheckResourceAttr(resourceName, "threshold_count", "3"), + resource.TestCheckResourceAttr(resourceName, "traffic_dial_percentage", "100"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccGlobalAcceleratorEndpointGroup_crossAccount(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.EndpointGroup + resourceName := "aws_globalaccelerator_endpoint_group.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEndpointGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEndpointGroupConfig_crossAccount(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEndpointGroupExists(ctx, resourceName, &v), + acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+/endpoint-group/[^/]+`)), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "0"), + resource.TestCheckResourceAttr(resourceName, "endpoint_group_region", acctest.Region()), + resource.TestCheckResourceAttr(resourceName, "health_check_interval_seconds", "30"), + resource.TestCheckResourceAttr(resourceName, "health_check_path", ""), + resource.TestCheckResourceAttr(resourceName, "health_check_port", "80"), + resource.TestCheckResourceAttr(resourceName, "health_check_protocol", "TCP"), + resource.TestCheckResourceAttr(resourceName, "cross_account_attachment_arn", "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43"), acctest.MatchResourceAttrGlobalARN(resourceName, "listener_arn", "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+`)), resource.TestCheckResourceAttr(resourceName, "port_override.#", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "threshold_count", acctest.Ct3), @@ -874,3 +914,28 @@ resource "aws_globalaccelerator_endpoint_group" "test" { } `, rName) } + +func testAccEndpointGroupConfig_crossAccount(rName string) string { + return fmt.Sprintf(` + resource "aws_globalaccelerator_accelerator" "test" { + name = %[1]q + ip_address_type = "IPV4" + enabled = false + } + + resource "aws_globalaccelerator_listener" "test" { + accelerator_arn = aws_globalaccelerator_accelerator.test.id + protocol = "TCP" + + port_range { + from_port = 80 + to_port = 80 + } + } + + resource "aws_globalaccelerator_endpoint_group" "test" { + listener_arn = aws_globalaccelerator_listener.test.id + cross_account_attachment_arn = "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43" + } + `, rName) +} diff --git a/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown b/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown index 68403ed80ca7..240dc6dd0b86 100644 --- a/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown +++ b/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown @@ -58,6 +58,7 @@ Terraform will only perform drift detection of its value when present in a confi **Note:** When client IP address preservation is enabled, the Global Accelerator service creates an EC2 Security Group in the VPC named `GlobalAccelerator` that must be deleted (potentially outside of Terraform) before the VPC will successfully delete. If this EC2 Security Group is not deleted, Terraform will retry the VPC deletion for a few minutes before reporting a `DependencyViolation` error. This cannot be resolved by re-running Terraform. * `endpoint_id` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID. * `weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify. +* `cross_account_attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. `port_override` supports the following arguments: diff --git a/website/docs/r/globalaccelerator_endpoint_group.html.markdown b/website/docs/r/globalaccelerator_endpoint_group.html.markdown index 05ed1d67baef..281c01058c33 100644 --- a/website/docs/r/globalaccelerator_endpoint_group.html.markdown +++ b/website/docs/r/globalaccelerator_endpoint_group.html.markdown @@ -45,6 +45,7 @@ Terraform will only perform drift detection of its value when present in a confi **Note:** When client IP address preservation is enabled, the Global Accelerator service creates an EC2 Security Group in the VPC named `GlobalAccelerator` that must be deleted (potentially outside of Terraform) before the VPC will successfully delete. If this EC2 Security Group is not deleted, Terraform will retry the VPC deletion for a few minutes before reporting a `DependencyViolation` error. This cannot be resolved by re-running Terraform. * `endpoint_id` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID. * `weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify. +* `cross_account_attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. `port_override` supports the following arguments: From 830a3d83c5d870f39f8054ebda84c510a2b994b0 Mon Sep 17 00:00:00 2001 From: Tiago Carreira Date: Thu, 26 Sep 2024 19:41:19 +0100 Subject: [PATCH 2/9] rename to attachment_arn (following the api) --- internal/service/globalaccelerator/endpoint_group.go | 4 ++-- internal/service/globalaccelerator/endpoint_group_test.go | 5 +++-- .../python/r/globalaccelerator_endpoint_group.html.markdown | 4 ++-- .../docs/r/globalaccelerator_endpoint_group.html.markdown | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index 2f818a261f36..71ba2645403f 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -68,7 +68,7 @@ func resourceEndpointGroup() *schema.Resource { Optional: true, ValidateFunc: validation.IntBetween(0, 255), }, - "cross_account_attachment_arn": { + "attachment_arn": { Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringLenBetween(1, 255), @@ -389,7 +389,7 @@ func expandEndpointConfiguration(tfMap map[string]interface{}) *awstypes.Endpoin apiObject.Weight = aws.Int32(int32(v)) } - if v, ok := tfMap["cross_account_attachment_arn"].(string); ok && v != "" { + if v, ok := tfMap["attachment_arn"].(string); ok && v != "" { apiObject.AttachmentArn = aws.String(v) } diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index dca1ea8b8006..d82c0c77f84f 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -85,7 +85,7 @@ func TestAccGlobalAcceleratorEndpointGroup_crossAccount(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "health_check_path", ""), resource.TestCheckResourceAttr(resourceName, "health_check_port", "80"), resource.TestCheckResourceAttr(resourceName, "health_check_protocol", "TCP"), - resource.TestCheckResourceAttr(resourceName, "cross_account_attachment_arn", "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43"), + resource.TestCheckResourceAttr(resourceName, "attachment_arn", "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43"), acctest.MatchResourceAttrGlobalARN(resourceName, "listener_arn", "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+`)), resource.TestCheckResourceAttr(resourceName, "port_override.#", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "threshold_count", acctest.Ct3), @@ -149,6 +149,7 @@ func TestAccGlobalAcceleratorEndpointGroup_ALBEndpoint_clientIP(t *testing.T) { resource.TestCheckTypeSetElemNestedAttrs(resourceName, "endpoint_configuration.*", map[string]string{ "client_ip_preservation_enabled": acctest.CtFalse, names.AttrWeight: "20", + "attachment_arn": "", }), resource.TestCheckTypeSetElemAttrPair(resourceName, "endpoint_configuration.*.endpoint_id", albResourceName, names.AttrID), resource.TestCheckResourceAttr(resourceName, "endpoint_group_region", acctest.Region()), @@ -935,7 +936,7 @@ func testAccEndpointGroupConfig_crossAccount(rName string) string { resource "aws_globalaccelerator_endpoint_group" "test" { listener_arn = aws_globalaccelerator_listener.test.id - cross_account_attachment_arn = "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43" + attachment_arn = "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43" } `, rName) } diff --git a/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown b/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown index 240dc6dd0b86..6d934b0d0ad5 100644 --- a/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown +++ b/website/docs/cdktf/python/r/globalaccelerator_endpoint_group.html.markdown @@ -58,7 +58,7 @@ Terraform will only perform drift detection of its value when present in a confi **Note:** When client IP address preservation is enabled, the Global Accelerator service creates an EC2 Security Group in the VPC named `GlobalAccelerator` that must be deleted (potentially outside of Terraform) before the VPC will successfully delete. If this EC2 Security Group is not deleted, Terraform will retry the VPC deletion for a few minutes before reporting a `DependencyViolation` error. This cannot be resolved by re-running Terraform. * `endpoint_id` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID. * `weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify. -* `cross_account_attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. +* `attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. `port_override` supports the following arguments: @@ -105,4 +105,4 @@ Using `terraform import`, import Global Accelerator endpoint groups using the `i % terraform import aws_globalaccelerator_endpoint_group.example arn:aws:globalaccelerator::111111111111:accelerator/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/listener/xxxxxxx/endpoint-group/xxxxxxxx ``` - \ No newline at end of file + diff --git a/website/docs/r/globalaccelerator_endpoint_group.html.markdown b/website/docs/r/globalaccelerator_endpoint_group.html.markdown index 281c01058c33..96bff7d4b571 100644 --- a/website/docs/r/globalaccelerator_endpoint_group.html.markdown +++ b/website/docs/r/globalaccelerator_endpoint_group.html.markdown @@ -45,7 +45,7 @@ Terraform will only perform drift detection of its value when present in a confi **Note:** When client IP address preservation is enabled, the Global Accelerator service creates an EC2 Security Group in the VPC named `GlobalAccelerator` that must be deleted (potentially outside of Terraform) before the VPC will successfully delete. If this EC2 Security Group is not deleted, Terraform will retry the VPC deletion for a few minutes before reporting a `DependencyViolation` error. This cannot be resolved by re-running Terraform. * `endpoint_id` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID. * `weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify. -* `cross_account_attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. +* `attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. `port_override` supports the following arguments: From 97f2951a729b21f0989ccefaa43f8cf0752477a9 Mon Sep 17 00:00:00 2001 From: Tiago Carreira Date: Thu, 26 Sep 2024 19:43:38 +0100 Subject: [PATCH 3/9] finish implementation: aws_globalaccelerator_endpoint_group.endpoint_configuration.attachment_arn --- .../globalaccelerator/endpoint_group.go | 81 +++++- .../globalaccelerator/endpoint_group_test.go | 240 +++++++++++++----- 2 files changed, 256 insertions(+), 65 deletions(-) diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index 71ba2645403f..53ad5beb07ce 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -5,10 +5,13 @@ package globalaccelerator import ( "context" + "errors" + "fmt" "log" "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/globalaccelerator" awstypes "github.com/aws/aws-sdk-go-v2/service/globalaccelerator/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -235,8 +238,13 @@ func resourceEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendFromErr(diags, err) } + crossAccountResources, err := getCrossAccountAttachementsFromResources(ctx, conn, endpointGroup.EndpointDescriptions) + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + d.Set(names.AttrARN, endpointGroup.EndpointGroupArn) - if err := d.Set("endpoint_configuration", flattenEndpointDescriptions(endpointGroup.EndpointDescriptions)); err != nil { + if err := d.Set("endpoint_configuration", flattenEndpointDescriptions(endpointGroup.EndpointDescriptions, crossAccountResources)); err != nil { return sdkdiag.AppendErrorf(diags, "setting endpoint_configuration: %s", err) } d.Set("endpoint_group_region", endpointGroup.EndpointGroupRegion) @@ -466,7 +474,7 @@ func expandPortOverrides(tfList []interface{}) []awstypes.PortOverride { return apiObjects } -func flattenEndpointDescription(apiObject *awstypes.EndpointDescription) map[string]interface{} { +func flattenEndpointDescription(apiObject *awstypes.EndpointDescription, crossAccountResources map[string]string) map[string]interface{} { if apiObject == nil { return nil } @@ -478,7 +486,11 @@ func flattenEndpointDescription(apiObject *awstypes.EndpointDescription) map[str } if v := apiObject.EndpointId; v != nil { - tfMap["endpoint_id"] = aws.ToString(v) + endpointId := aws.ToString(v) + tfMap["endpoint_id"] = endpointId + if crossAccountAttachment, ok := crossAccountResources[endpointId]; ok { + tfMap["attachment_arn"] = crossAccountAttachment + } } if v := apiObject.Weight; v != nil { @@ -488,7 +500,7 @@ func flattenEndpointDescription(apiObject *awstypes.EndpointDescription) map[str return tfMap } -func flattenEndpointDescriptions(apiObjects []awstypes.EndpointDescription) []interface{} { +func flattenEndpointDescriptions(apiObjects []awstypes.EndpointDescription, crossAccountResources map[string]string) []interface{} { if len(apiObjects) == 0 { return nil } @@ -496,7 +508,7 @@ func flattenEndpointDescriptions(apiObjects []awstypes.EndpointDescription) []in var tfList []interface{} for _, apiObject := range apiObjects { - tfList = append(tfList, flattenEndpointDescription(&apiObject)) + tfList = append(tfList, flattenEndpointDescription(&apiObject, crossAccountResources)) } return tfList @@ -533,3 +545,62 @@ func flattenPortOverrides(apiObjects []awstypes.PortOverride) []interface{} { return tfList } + +func listAllCrossAccountResourcesByOwner(ctx context.Context, conn *globalaccelerator.Client, accountId string) ([]awstypes.CrossAccountResource, error) { + accountOwnerResources := []awstypes.CrossAccountResource{} + + var nextToken *string + for { + crossResourcesResult, err := conn.ListCrossAccountResources(ctx, &globalaccelerator.ListCrossAccountResourcesInput{ + ResourceOwnerAwsAccountId: aws.String(accountId), + NextToken: nextToken, + }) + if err != nil { + return accountOwnerResources, err + } + accountOwnerResources = append(accountOwnerResources, crossResourcesResult.CrossAccountResources...) + + if crossResourcesResult.NextToken == nil { + break + } + nextToken = crossResourcesResult.NextToken + } + + return accountOwnerResources, nil +} + +// getCrossAccountAttachementsFromResources returns a map[endpointId]attachmentARN +func getCrossAccountAttachementsFromResources(ctx context.Context, conn *globalaccelerator.Client, egDescriptions []awstypes.EndpointDescription) (map[string]string, error) { + tmpErrors := []error{} + + // EndpointId -> AttachmentArn + result := map[string]string{} + + if len(egDescriptions) == 0 { + return result, nil + } + + queriedAccounts := map[string][]awstypes.CrossAccountResource{} // cache + for _, egDescription := range egDescriptions { + arn, err := arn.Parse(*egDescription.EndpointId) + if err != nil { + continue // not an arn, not a crossAccountResource + } + + if _, ok := queriedAccounts[arn.AccountID]; !ok { + queriedAccounts[arn.AccountID], err = listAllCrossAccountResourcesByOwner(ctx, conn, arn.AccountID) + if err != nil { + tmpErrors = append(tmpErrors, fmt.Errorf("failed to ListCrossAccountResources for account %q: %w", arn.AccountID, err)) + } + } + + for _, crossAccResource := range queriedAccounts[arn.AccountID] { + if *crossAccResource.EndpointId == *egDescription.EndpointId { + result[*crossAccResource.EndpointId] = *crossAccResource.AttachmentArn + break + } + } + } + + return result, errors.Join(tmpErrors...) +} diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index d82c0c77f84f..83e3cb3942d7 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -46,46 +46,6 @@ func TestAccGlobalAcceleratorEndpointGroup_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "health_check_path", ""), resource.TestCheckResourceAttr(resourceName, "health_check_port", "80"), resource.TestCheckResourceAttr(resourceName, "health_check_protocol", "TCP"), - resource.TestCheckResourceAttr(resourceName, "cross_account_attachment_arn", ""), - acctest.MatchResourceAttrGlobalARN(resourceName, "listener_arn", "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+`)), - resource.TestCheckResourceAttr(resourceName, "port_override.#", "0"), - resource.TestCheckResourceAttr(resourceName, "threshold_count", "3"), - resource.TestCheckResourceAttr(resourceName, "traffic_dial_percentage", "100"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccGlobalAcceleratorEndpointGroup_crossAccount(t *testing.T) { - ctx := acctest.Context(t) - var v awstypes.EndpointGroup - resourceName := "aws_globalaccelerator_endpoint_group.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckEndpointGroupDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccEndpointGroupConfig_crossAccount(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckEndpointGroupExists(ctx, resourceName, &v), - acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+/endpoint-group/[^/]+`)), - resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "0"), - resource.TestCheckResourceAttr(resourceName, "endpoint_group_region", acctest.Region()), - resource.TestCheckResourceAttr(resourceName, "health_check_interval_seconds", "30"), - resource.TestCheckResourceAttr(resourceName, "health_check_path", ""), - resource.TestCheckResourceAttr(resourceName, "health_check_port", "80"), - resource.TestCheckResourceAttr(resourceName, "health_check_protocol", "TCP"), - resource.TestCheckResourceAttr(resourceName, "attachment_arn", "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43"), acctest.MatchResourceAttrGlobalARN(resourceName, "listener_arn", "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+`)), resource.TestCheckResourceAttr(resourceName, "port_override.#", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "threshold_count", acctest.Ct3), @@ -470,6 +430,46 @@ func TestAccGlobalAcceleratorEndpointGroup_update(t *testing.T) { }) } +func TestAccGlobalAcceleratorEndpointGroup_crossAccountAttachment(t *testing.T) { + ctx := acctest.Context(t) + var v awstypes.EndpointGroup + resourceName := "aws_globalaccelerator_endpoint_group.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckOrganizationsAccount(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5FactoriesAlternate(ctx, t), + CheckDestroy: testAccCheckEndpointGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEndpointGroupConfig_crossAccountAttachement(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEndpointGroupExists(ctx, resourceName, &v), + acctest.MatchResourceAttrGlobalARN(resourceName, names.AttrARN, "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+/endpoint-group/[^/]+`)), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", acctest.Ct1), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "endpoint_configuration.*", map[string]string{ + "client_ip_preservation_enabled": acctest.CtFalse, + names.AttrWeight: "20", + }), + resource.TestCheckTypeSetElemAttrPair(resourceName, "endpoint_configuration.*.endpoint_id", "aws_lb.alt_test", names.AttrARN), + resource.TestCheckTypeSetElemAttrPair(resourceName, "endpoint_configuration.*.attachment_arn", "aws_globalaccelerator_cross_account_attachment.alt_test", names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "endpoint_group_region", acctest.AlternateRegion()), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckEndpointGroupExists(ctx context.Context, name string, v *awstypes.EndpointGroup) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] @@ -916,27 +916,147 @@ resource "aws_globalaccelerator_endpoint_group" "test" { `, rName) } -func testAccEndpointGroupConfig_crossAccount(rName string) string { - return fmt.Sprintf(` - resource "aws_globalaccelerator_accelerator" "test" { - name = %[1]q - ip_address_type = "IPV4" - enabled = false - } +func testAccEndpointGroupConfig_crossAccountAttachement(rName string) string { + return acctest.ConfigCompose( + acctest.ConfigAlternateAccountAlternateRegionProvider(), + fmt.Sprintf(` +############################################################################### +## alternate account setup +############################################################################### - resource "aws_globalaccelerator_listener" "test" { - accelerator_arn = aws_globalaccelerator_accelerator.test.id - protocol = "TCP" +data "aws_availability_zones" "alt_available" { + provider = "awsalternate" - port_range { - from_port = 80 - to_port = 80 - } - } + exclude_zone_ids = ["usw2-az4", "usgw1-az2"] + state = "available" - resource "aws_globalaccelerator_endpoint_group" "test" { - listener_arn = aws_globalaccelerator_listener.test.id - attachment_arn = "arn:aws:elasticloadbalancing:us-west-1:111111111111:loadbalancer/net/nlb-01/8a6825aea9cdab43" - } - `, rName) + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "alt_test" { + provider = "awsalternate" + + cidr_block = "10.0.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "alt_test" { + provider = "awsalternate" + + count = 2 + + vpc_id = aws_vpc.alt_test.id + availability_zone = data.aws_availability_zones.alt_available.names[count.index] + cidr_block = cidrsubnet(aws_vpc.alt_test.cidr_block, 8, count.index) + + tags = { + Name = %[1]q + } +} + +resource "aws_lb" "alt_test" { + provider = "awsalternate" + + name = %[1]q + internal = false + security_groups = [aws_security_group.alt_test.id] + subnets = aws_subnet.alt_test[*].id + + idle_timeout = 30 + enable_deletion_protection = false + + tags = { + Name = %[1]q + } +} + +resource "aws_security_group" "alt_test" { + provider = "awsalternate" + + name = %[1]q + vpc_id = aws_vpc.alt_test.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "alt_test" { + provider = "awsalternate" + + vpc_id = aws_vpc.alt_test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_globalaccelerator_cross_account_attachment" "alt_test" { + provider = "awsalternate" + + name = %[1]q + principals = [ data.aws_caller_identity.current.account_id ] + + resource { + endpoint_id = aws_lb.alt_test.arn + } +} + + +############################################################################### +## main account +############################################################################### + +data "aws_caller_identity" "current" {} + +resource "aws_globalaccelerator_accelerator" "test" { + name = %[1]q + ip_address_type = "IPV4" + enabled = false +} + +resource "aws_globalaccelerator_listener" "test" { + accelerator_arn = aws_globalaccelerator_accelerator.test.id + protocol = "TCP" + + port_range { + from_port = 80 + to_port = 80 + } +} + +resource "aws_globalaccelerator_endpoint_group" "test" { + listener_arn = aws_globalaccelerator_listener.test.id + + endpoint_configuration { + endpoint_id = aws_lb.alt_test.arn + attachment_arn = aws_globalaccelerator_cross_account_attachment.alt_test.arn + weight = 20 + client_ip_preservation_enabled = false + } + + endpoint_group_region = %[2]q +} +`, rName, acctest.AlternateRegion()), + ) } From a7c2c9164d83c947c52f21d040a198f1d17dedbb Mon Sep 17 00:00:00 2001 From: Tiago Carreira Date: Thu, 26 Sep 2024 19:49:57 +0100 Subject: [PATCH 4/9] add changelog for this PR --- .changelog/39507.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/39507.txt diff --git a/.changelog/39507.txt b/.changelog/39507.txt new file mode 100644 index 000000000000..392a1af834c0 --- /dev/null +++ b/.changelog/39507.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_globalaccelerator_endpoint_group: Add attachment_arn as a new (optional) field inside endpoint_configuration +``` From 9df60246670ab768c0493f77705732f507c0fe99 Mon Sep 17 00:00:00 2001 From: Tiago Carreira Date: Tue, 1 Oct 2024 10:12:03 +0100 Subject: [PATCH 5/9] simplify algorithm --- .../globalaccelerator/endpoint_group.go | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index 53ad5beb07ce..e98c1b548f8c 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -569,7 +569,7 @@ func listAllCrossAccountResourcesByOwner(ctx context.Context, conn *globalaccele return accountOwnerResources, nil } -// getCrossAccountAttachementsFromResources returns a map[endpointId]attachmentARN +// getCrossAccountAttachementsFromResources returns a map[endpointId]attachmentARN (may include unused endpointId/attachmentARN) func getCrossAccountAttachementsFromResources(ctx context.Context, conn *globalaccelerator.Client, egDescriptions []awstypes.EndpointDescription) (map[string]string, error) { tmpErrors := []error{} @@ -580,25 +580,25 @@ func getCrossAccountAttachementsFromResources(ctx context.Context, conn *globala return result, nil } - queriedAccounts := map[string][]awstypes.CrossAccountResource{} // cache + queriedAccounts := map[string]bool{} // cache for _, egDescription := range egDescriptions { arn, err := arn.Parse(*egDescription.EndpointId) if err != nil { continue // not an arn, not a crossAccountResource } - if _, ok := queriedAccounts[arn.AccountID]; !ok { - queriedAccounts[arn.AccountID], err = listAllCrossAccountResourcesByOwner(ctx, conn, arn.AccountID) - if err != nil { - tmpErrors = append(tmpErrors, fmt.Errorf("failed to ListCrossAccountResources for account %q: %w", arn.AccountID, err)) - } + if queriedAccounts[arn.AccountID] { + continue + } + queriedAccounts[arn.AccountID] = true + + accountResourcesResult, err := listAllCrossAccountResourcesByOwner(ctx, conn, arn.AccountID) + if err != nil { + tmpErrors = append(tmpErrors, fmt.Errorf("failed to ListCrossAccountResources for account %q: %w", arn.AccountID, err)) } - for _, crossAccResource := range queriedAccounts[arn.AccountID] { - if *crossAccResource.EndpointId == *egDescription.EndpointId { - result[*crossAccResource.EndpointId] = *crossAccResource.AttachmentArn - break - } + for _, crossAccResource := range accountResourcesResult { + result[*crossAccResource.EndpointId] = *crossAccResource.AttachmentArn } } From 756a17766ae4341ede649b06c390e8054cf2d804 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 1 Oct 2024 12:28:05 -0400 Subject: [PATCH 6/9] Cosmetics. --- .changelog/39507.txt | 2 +- .../globalaccelerator/endpoint_group.go | 113 ++++++++---------- .../globalaccelerator/endpoint_group_test.go | 17 ++- ...alaccelerator_endpoint_group.html.markdown | 2 +- 4 files changed, 60 insertions(+), 74 deletions(-) diff --git a/.changelog/39507.txt b/.changelog/39507.txt index 392a1af834c0..a4a55c44481f 100644 --- a/.changelog/39507.txt +++ b/.changelog/39507.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -resource/aws_globalaccelerator_endpoint_group: Add attachment_arn as a new (optional) field inside endpoint_configuration +resource/aws_globalaccelerator_endpoint_group: Add `endpoint_configuration.attachment_arn` argument ``` diff --git a/internal/service/globalaccelerator/endpoint_group.go b/internal/service/globalaccelerator/endpoint_group.go index e98c1b548f8c..8fc97f32bb82 100644 --- a/internal/service/globalaccelerator/endpoint_group.go +++ b/internal/service/globalaccelerator/endpoint_group.go @@ -5,8 +5,6 @@ package globalaccelerator import ( "context" - "errors" - "fmt" "log" "time" @@ -56,6 +54,11 @@ func resourceEndpointGroup() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "attachment_arn": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidARN, + }, "client_ip_preservation_enabled": { Type: schema.TypeBool, Optional: true, @@ -71,11 +74,6 @@ func resourceEndpointGroup() *schema.Resource { Optional: true, ValidateFunc: validation.IntBetween(0, 255), }, - "attachment_arn": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringLenBetween(1, 255), - }, }, }, }, @@ -238,13 +236,13 @@ func resourceEndpointGroupRead(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendFromErr(diags, err) } - crossAccountResources, err := getCrossAccountAttachementsFromResources(ctx, conn, endpointGroup.EndpointDescriptions) + crossAccountAttachments, err := findCrossAccountAttachments(ctx, conn, endpointGroup.EndpointDescriptions) if err != nil { - return sdkdiag.AppendFromErr(diags, err) + return sdkdiag.AppendErrorf(diags, "reading Global Accelerator Endpoint Group (%s) cross-account attachments: %s", d.Id(), err) } d.Set(names.AttrARN, endpointGroup.EndpointGroupArn) - if err := d.Set("endpoint_configuration", flattenEndpointDescriptions(endpointGroup.EndpointDescriptions, crossAccountResources)); err != nil { + if err := d.Set("endpoint_configuration", flattenEndpointDescriptions(endpointGroup.EndpointDescriptions, crossAccountAttachments)); err != nil { return sdkdiag.AppendErrorf(diags, "setting endpoint_configuration: %s", err) } d.Set("endpoint_group_region", endpointGroup.EndpointGroupRegion) @@ -385,6 +383,10 @@ func expandEndpointConfiguration(tfMap map[string]interface{}) *awstypes.Endpoin apiObject := &awstypes.EndpointConfiguration{} + if v, ok := tfMap["attachment_arn"].(string); ok && v != "" { + apiObject.AttachmentArn = aws.String(v) + } + if v, ok := tfMap["client_ip_preservation_enabled"].(bool); ok { apiObject.ClientIPPreservationEnabled = aws.Bool(v) } @@ -397,10 +399,6 @@ func expandEndpointConfiguration(tfMap map[string]interface{}) *awstypes.Endpoin apiObject.Weight = aws.Int32(int32(v)) } - if v, ok := tfMap["attachment_arn"].(string); ok && v != "" { - apiObject.AttachmentArn = aws.String(v) - } - return apiObject } @@ -474,7 +472,7 @@ func expandPortOverrides(tfList []interface{}) []awstypes.PortOverride { return apiObjects } -func flattenEndpointDescription(apiObject *awstypes.EndpointDescription, crossAccountResources map[string]string) map[string]interface{} { +func flattenEndpointDescription(apiObject *awstypes.EndpointDescription, crossAccountAttachments map[string]string) map[string]interface{} { if apiObject == nil { return nil } @@ -486,10 +484,11 @@ func flattenEndpointDescription(apiObject *awstypes.EndpointDescription, crossAc } if v := apiObject.EndpointId; v != nil { - endpointId := aws.ToString(v) - tfMap["endpoint_id"] = endpointId - if crossAccountAttachment, ok := crossAccountResources[endpointId]; ok { - tfMap["attachment_arn"] = crossAccountAttachment + v := aws.ToString(v) + tfMap["endpoint_id"] = v + + if v, ok := crossAccountAttachments[v]; ok { + tfMap["attachment_arn"] = v } } @@ -500,7 +499,7 @@ func flattenEndpointDescription(apiObject *awstypes.EndpointDescription, crossAc return tfMap } -func flattenEndpointDescriptions(apiObjects []awstypes.EndpointDescription, crossAccountResources map[string]string) []interface{} { +func flattenEndpointDescriptions(apiObjects []awstypes.EndpointDescription, crossAccountAttachments map[string]string) []interface{} { if len(apiObjects) == 0 { return nil } @@ -508,7 +507,7 @@ func flattenEndpointDescriptions(apiObjects []awstypes.EndpointDescription, cros var tfList []interface{} for _, apiObject := range apiObjects { - tfList = append(tfList, flattenEndpointDescription(&apiObject, crossAccountResources)) + tfList = append(tfList, flattenEndpointDescription(&apiObject, crossAccountAttachments)) } return tfList @@ -546,61 +545,51 @@ func flattenPortOverrides(apiObjects []awstypes.PortOverride) []interface{} { return tfList } -func listAllCrossAccountResourcesByOwner(ctx context.Context, conn *globalaccelerator.Client, accountId string) ([]awstypes.CrossAccountResource, error) { - accountOwnerResources := []awstypes.CrossAccountResource{} +func findCrossAccountAttachments(ctx context.Context, conn *globalaccelerator.Client, endpointDescriptions []awstypes.EndpointDescription) (map[string]string, error) { + crossAccountAttachments := map[string]string{} - var nextToken *string - for { - crossResourcesResult, err := conn.ListCrossAccountResources(ctx, &globalaccelerator.ListCrossAccountResourcesInput{ - ResourceOwnerAwsAccountId: aws.String(accountId), - NextToken: nextToken, - }) + accounts := map[string]bool{} + for _, endpointDescription := range endpointDescriptions { + arn, err := arn.Parse(aws.ToString(endpointDescription.EndpointId)) if err != nil { - return accountOwnerResources, err + continue // Not an ARN => not a cross-account resource. } - accountOwnerResources = append(accountOwnerResources, crossResourcesResult.CrossAccountResources...) - if crossResourcesResult.NextToken == nil { - break + accountID := arn.AccountID + if accounts[accountID] { + continue } - nextToken = crossResourcesResult.NextToken - } - - return accountOwnerResources, nil -} - -// getCrossAccountAttachementsFromResources returns a map[endpointId]attachmentARN (may include unused endpointId/attachmentARN) -func getCrossAccountAttachementsFromResources(ctx context.Context, conn *globalaccelerator.Client, egDescriptions []awstypes.EndpointDescription) (map[string]string, error) { - tmpErrors := []error{} - - // EndpointId -> AttachmentArn - result := map[string]string{} - - if len(egDescriptions) == 0 { - return result, nil - } + accounts[accountID] = true - queriedAccounts := map[string]bool{} // cache - for _, egDescription := range egDescriptions { - arn, err := arn.Parse(*egDescription.EndpointId) + input := &globalaccelerator.ListCrossAccountResourcesInput{ + ResourceOwnerAwsAccountId: aws.String(accountID), + } + crossAccountResources, err := findCrossAccountResources(ctx, conn, input) if err != nil { - continue // not an arn, not a crossAccountResource + return nil, err } - if queriedAccounts[arn.AccountID] { - continue + for _, crossAccountResource := range crossAccountResources { + crossAccountAttachments[aws.ToString(crossAccountResource.EndpointId)] = aws.ToString(crossAccountResource.AttachmentArn) } - queriedAccounts[arn.AccountID] = true + } + + return crossAccountAttachments, nil +} + +func findCrossAccountResources(ctx context.Context, conn *globalaccelerator.Client, input *globalaccelerator.ListCrossAccountResourcesInput) ([]awstypes.CrossAccountResource, error) { + var output []awstypes.CrossAccountResource + + pages := globalaccelerator.NewListCrossAccountResourcesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) - accountResourcesResult, err := listAllCrossAccountResourcesByOwner(ctx, conn, arn.AccountID) if err != nil { - tmpErrors = append(tmpErrors, fmt.Errorf("failed to ListCrossAccountResources for account %q: %w", arn.AccountID, err)) + return nil, err } - for _, crossAccResource := range accountResourcesResult { - result[*crossAccResource.EndpointId] = *crossAccResource.AttachmentArn - } + output = append(output, page.CrossAccountResources...) } - return result, errors.Join(tmpErrors...) + return output, nil } diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index 83e3cb3942d7..95863d4393ce 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -107,9 +107,9 @@ func TestAccGlobalAcceleratorEndpointGroup_ALBEndpoint_clientIP(t *testing.T) { acctest.MatchResourceAttrGlobalARN(resourceName, names.AttrARN, "globalaccelerator", regexache.MustCompile(`accelerator/[^/]+/listener/[^/]+/endpoint-group/[^/]+`)), resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "endpoint_configuration.*", map[string]string{ + "attachment_arn": "", "client_ip_preservation_enabled": acctest.CtFalse, names.AttrWeight: "20", - "attachment_arn": "", }), resource.TestCheckTypeSetElemAttrPair(resourceName, "endpoint_configuration.*.endpoint_id", albResourceName, names.AttrID), resource.TestCheckResourceAttr(resourceName, "endpoint_group_region", acctest.Region()), @@ -439,8 +439,9 @@ func TestAccGlobalAcceleratorEndpointGroup_crossAccountAttachment(t *testing.T) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckOrganizationsAccount(ctx, t) testAccPreCheck(ctx, t) + acctest.PreCheckMultipleRegion(t, 2) + acctest.PreCheckAlternateAccount(t) }, ErrorCheck: acctest.ErrorCheck(t, names.GlobalAcceleratorServiceID), ProtoV5ProviderFactories: acctest.ProtoV5FactoriesAlternate(ctx, t), @@ -456,8 +457,8 @@ func TestAccGlobalAcceleratorEndpointGroup_crossAccountAttachment(t *testing.T) "client_ip_preservation_enabled": acctest.CtFalse, names.AttrWeight: "20", }), - resource.TestCheckTypeSetElemAttrPair(resourceName, "endpoint_configuration.*.endpoint_id", "aws_lb.alt_test", names.AttrARN), resource.TestCheckTypeSetElemAttrPair(resourceName, "endpoint_configuration.*.attachment_arn", "aws_globalaccelerator_cross_account_attachment.alt_test", names.AttrARN), + resource.TestCheckTypeSetElemAttrPair(resourceName, "endpoint_configuration.*.endpoint_id", "aws_lb.alt_test", names.AttrARN), resource.TestCheckResourceAttr(resourceName, "endpoint_group_region", acctest.AlternateRegion()), ), }, @@ -921,9 +922,8 @@ func testAccEndpointGroupConfig_crossAccountAttachement(rName string) string { acctest.ConfigAlternateAccountAlternateRegionProvider(), fmt.Sprintf(` ############################################################################### -## alternate account setup +## Alternate account setup. ############################################################################### - data "aws_availability_zones" "alt_available" { provider = "awsalternate" @@ -1022,11 +1022,9 @@ resource "aws_globalaccelerator_cross_account_attachment" "alt_test" { } } - ############################################################################### -## main account +## Main account setup. ############################################################################### - data "aws_caller_identity" "current" {} resource "aws_globalaccelerator_accelerator" "test" { @@ -1057,6 +1055,5 @@ resource "aws_globalaccelerator_endpoint_group" "test" { endpoint_group_region = %[2]q } -`, rName, acctest.AlternateRegion()), - ) +`, rName, acctest.AlternateRegion())) } diff --git a/website/docs/r/globalaccelerator_endpoint_group.html.markdown b/website/docs/r/globalaccelerator_endpoint_group.html.markdown index 96bff7d4b571..92cabd5b9ca1 100644 --- a/website/docs/r/globalaccelerator_endpoint_group.html.markdown +++ b/website/docs/r/globalaccelerator_endpoint_group.html.markdown @@ -41,11 +41,11 @@ Terraform will only perform drift detection of its value when present in a confi `endpoint_configuration` supports the following arguments: +* `attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. * `client_ip_preservation_enabled` - (Optional) Indicates whether client IP address preservation is enabled for an Application Load Balancer endpoint. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/preserve-client-ip-address.html) for more details. The default value is `false`. **Note:** When client IP address preservation is enabled, the Global Accelerator service creates an EC2 Security Group in the VPC named `GlobalAccelerator` that must be deleted (potentially outside of Terraform) before the VPC will successfully delete. If this EC2 Security Group is not deleted, Terraform will retry the VPC deletion for a few minutes before reporting a `DependencyViolation` error. This cannot be resolved by re-running Terraform. * `endpoint_id` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID. * `weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify. -* `attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. `port_override` supports the following arguments: From 83d8794c694d1d028416c4175d3c7032f12d26f1 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 1 Oct 2024 15:07:45 -0400 Subject: [PATCH 7/9] Fix markdown-lint 'MD030/list-marker-space Spaces after list markers [Expected: 1; Actual: 2]'. --- website/docs/r/globalaccelerator_endpoint_group.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/globalaccelerator_endpoint_group.html.markdown b/website/docs/r/globalaccelerator_endpoint_group.html.markdown index 92cabd5b9ca1..655314198432 100644 --- a/website/docs/r/globalaccelerator_endpoint_group.html.markdown +++ b/website/docs/r/globalaccelerator_endpoint_group.html.markdown @@ -41,7 +41,7 @@ Terraform will only perform drift detection of its value when present in a confi `endpoint_configuration` supports the following arguments: -* `attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. +* `attachment_arn` - (Optional) An ARN of an exposed cross-account attachment. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/cross-account-resources.html) for more details. * `client_ip_preservation_enabled` - (Optional) Indicates whether client IP address preservation is enabled for an Application Load Balancer endpoint. See the [AWS documentation](https://docs.aws.amazon.com/global-accelerator/latest/dg/preserve-client-ip-address.html) for more details. The default value is `false`. **Note:** When client IP address preservation is enabled, the Global Accelerator service creates an EC2 Security Group in the VPC named `GlobalAccelerator` that must be deleted (potentially outside of Terraform) before the VPC will successfully delete. If this EC2 Security Group is not deleted, Terraform will retry the VPC deletion for a few minutes before reporting a `DependencyViolation` error. This cannot be resolved by re-running Terraform. * `endpoint_id` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID. From a6c22fc9d92f3004a5ad9ebc2cfcc6abfe889099 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 1 Oct 2024 15:09:22 -0400 Subject: [PATCH 8/9] Fix terrafmt errors. --- internal/service/globalaccelerator/endpoint_group_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index 95863d4393ce..3bc975bf5f71 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -1013,9 +1013,9 @@ resource "aws_internet_gateway" "alt_test" { resource "aws_globalaccelerator_cross_account_attachment" "alt_test" { provider = "awsalternate" - + name = %[1]q - principals = [ data.aws_caller_identity.current.account_id ] + principals = [ data.aws_caller_identity.current.account_id ] resource { endpoint_id = aws_lb.alt_test.arn @@ -1045,7 +1045,7 @@ resource "aws_globalaccelerator_listener" "test" { resource "aws_globalaccelerator_endpoint_group" "test" { listener_arn = aws_globalaccelerator_listener.test.id - + endpoint_configuration { endpoint_id = aws_lb.alt_test.arn attachment_arn = aws_globalaccelerator_cross_account_attachment.alt_test.arn From 98aa21e27aa8761272f870a46290c6910787d911 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 1 Oct 2024 15:11:48 -0400 Subject: [PATCH 9/9] Fix terrafmt errors. --- internal/service/globalaccelerator/endpoint_group_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/globalaccelerator/endpoint_group_test.go b/internal/service/globalaccelerator/endpoint_group_test.go index 3bc975bf5f71..ef8b44c4da60 100644 --- a/internal/service/globalaccelerator/endpoint_group_test.go +++ b/internal/service/globalaccelerator/endpoint_group_test.go @@ -1015,7 +1015,7 @@ resource "aws_globalaccelerator_cross_account_attachment" "alt_test" { provider = "awsalternate" name = %[1]q - principals = [ data.aws_caller_identity.current.account_id ] + principals = [data.aws_caller_identity.current.account_id] resource { endpoint_id = aws_lb.alt_test.arn