From 525300a5180538b694396ef2cd90e8d4ae943de1 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 18 Oct 2023 15:48:53 -0400 Subject: [PATCH 1/7] Add attribute to schema and CRUD functions --- internal/service/elbv2/load_balancer.go | 29 ++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index e753f1eedf3..a844fdc5f09 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -119,6 +119,15 @@ func ResourceLoadBalancer() *schema.Resource { Type: schema.TypeString, Computed: true, }, + // "dns_record_client_routing_policy": { + // Type: schema.TypeString, + // Optional: true, + // ValidateFunc: validation.StringInSlice([]string{ + // "availability_zone_affinity", + // "partial_availability_zone_affinity", + // "any_availability_zone", + // }, false), + // }, "drop_invalid_header_fields": { Type: schema.TypeBool, Optional: true, @@ -527,7 +536,21 @@ func resourceLoadBalancerUpdate(ctx context.Context, d *schema.ResourceData, met }) } - case elbv2.LoadBalancerTypeEnumGateway, elbv2.LoadBalancerTypeEnumNetwork: + case elbv2.LoadBalancerTypeEnumGateway: + if d.HasChange("enable_cross_zone_load_balancing") || d.IsNewResource() { + attributes = append(attributes, &elbv2.LoadBalancerAttribute{ + Key: aws.String("load_balancing.cross_zone.enabled"), + Value: aws.String(fmt.Sprintf("%t", d.Get("enable_cross_zone_load_balancing").(bool))), + }) + } + + case elbv2.LoadBalancerTypeEnumNetwork: + if d.HasChange("dns_record_client_routing_policy") || d.IsNewResource() { + attributes = append(attributes, &elbv2.LoadBalancerAttribute{ + Key: aws.String("dns_record.client_routing_policy"), + Value: aws.String(d.Get("dns_record_client_routing_policy").(string)), + }) + } if d.HasChange("enable_cross_zone_load_balancing") || d.IsNewResource() { attributes = append(attributes, &elbv2.LoadBalancerAttribute{ Key: aws.String("load_balancing.cross_zone.enabled"), @@ -955,6 +978,10 @@ func flattenResource(ctx context.Context, d *schema.ResourceData, meta interface accessLogMap["bucket"] = aws.StringValue(attr.Value) case "access_logs.s3.prefix": accessLogMap["prefix"] = aws.StringValue(attr.Value) + case "dns_record.client_routing_policy": + dnsClientRoutingPolicy := aws.StringValue(attr.Value) + log.Printf("[DEBUG] Setting NLB DNS Record Client Routing Policy: %s", dnsClientRoutingPolicy) + d.Set("dns_record_client_routing_policy", dnsClientRoutingPolicy) case "idle_timeout.timeout_seconds": timeout, err := strconv.Atoi(aws.StringValue(attr.Value)) if err != nil { From 654aee93b8c248a6a30cd46ba4e35c935db9fe75 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:04:07 -0400 Subject: [PATCH 2/7] [WIP] Add acceptance tests --- internal/service/elbv2/load_balancer.go | 18 ++-- internal/service/elbv2/load_balancer_test.go | 99 ++++++++++++++++++++ 2 files changed, 108 insertions(+), 9 deletions(-) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index a844fdc5f09..d402c4a628a 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -119,15 +119,15 @@ func ResourceLoadBalancer() *schema.Resource { Type: schema.TypeString, Computed: true, }, - // "dns_record_client_routing_policy": { - // Type: schema.TypeString, - // Optional: true, - // ValidateFunc: validation.StringInSlice([]string{ - // "availability_zone_affinity", - // "partial_availability_zone_affinity", - // "any_availability_zone", - // }, false), - // }, + "dns_record_client_routing_policy": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "availability_zone_affinity", + "partial_availability_zone_affinity", + "any_availability_zone", + }, false), + }, "drop_invalid_header_fields": { Type: schema.TypeBool, Optional: true, diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index b8b5a3d7ba4..9d8dd696384 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -1304,6 +1304,48 @@ func TestAccELBV2LoadBalancer_NetworkLoadBalancer_accessLogsPrefix(t *testing.T) }) } +func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateDNSRecordClientRoutingPolicy(t *testing.T) { + ctx := acctest.Context(t) + var conf elbv2.LoadBalancer + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_lb.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, elbv2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLoadBalancerDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyAffinity(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "dns_record_client_routing_policy", "availability_zone_affinity"), + ), + }, + { + Config: testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyPartialAffinity(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "dns_record_client_routing_policy", "partial_availability_zone_affinity"), + ), + }, + { + Config: testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyAnyAvailabilityZone(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "dns_record_client_routing_policy", "any_availability_zone"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccELBV2LoadBalancer_NetworkLoadBalancer_updateSecurityGroups(t *testing.T) { ctx := acctest.Context(t) var lb1, lb2, lb3, lb4 elbv2.LoadBalancer @@ -2226,6 +2268,63 @@ resource "aws_subnet" "test" { `, rName)) } +func testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyAffinity(rName string) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` +resource "aws_lb" "test" { + name = %[1]q + dns_record_client_routing_policy = "availability_zone_affinity" + internal = true + load_balancer_type = "network" + + subnet_mapping { + subnet_id = aws_subnet.test[0].id + } + + tags = { + Name = %[1]q + } +} +`, rName)) +} + +func testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyAnyAvailabilityZone(rName string) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` +resource "aws_lb" "test" { + name = %[1]q + dns_record_client_routing_policy = "any_availability_zone" + internal = true + load_balancer_type = "network" + + subnet_mapping { + subnet_id = aws_subnet.test[0].id + } + + tags = { + Name = %[1]q + } +} +`, rName)) +} + +func testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyPartialAffinity(rName string) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` +resource "aws_lb" "test" { + name = %[1]q + dns_record_client_routing_policy = "partial_availability_zone_affinity" + internal = true + load_balancer_type = "network" + + subnet_mapping { + subnet_id = aws_subnet.test[0].id + } + + tags = { + Name = %[1]q + } +} +`, rName)) +} + func testAccLoadBalancerConfig_backwardsCompatibility(rName string) string { return acctest.ConfigCompose(testAccLoadBalancerConfig_baseInternal(rName, 2), fmt.Sprintf(` resource "aws_alb" "test" { From d26d1474af4914d8c58ca84f993c9fd868d7ce86 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 18 Oct 2023 17:25:13 -0400 Subject: [PATCH 3/7] Add acceptance tests --- internal/service/elbv2/load_balancer.go | 6 ++++-- internal/service/elbv2/load_balancer_test.go | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index d402c4a628a..99829d243e7 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -120,8 +120,10 @@ func ResourceLoadBalancer() *schema.Resource { Computed: true, }, "dns_record_client_routing_policy": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Default: "any_availability_zone", + DiffSuppressFunc: suppressIfLBTypeNot(elbv2.LoadBalancerTypeEnumNetwork), ValidateFunc: validation.StringInSlice([]string{ "availability_zone_affinity", "partial_availability_zone_affinity", diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index 9d8dd696384..44799da8965 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -128,6 +128,7 @@ func TestAccELBV2LoadBalancer_NLB_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "access_logs.0.enabled", "false"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "elasticloadbalancing", regexache.MustCompile(fmt.Sprintf("loadbalancer/net/%s/.+", rName))), resource.TestCheckResourceAttrSet(resourceName, "dns_name"), + resource.TestCheckResourceAttr(resourceName, "dns_record_client_routing_policy", "any_availability_zone"), resource.TestCheckResourceAttr(resourceName, "enable_deletion_protection", "false"), resource.TestCheckResourceAttr(resourceName, "internal", "true"), resource.TestCheckResourceAttr(resourceName, "ip_address_type", "ipv4"), From 3d1011b8af85a55a9daa4e19d692ab0a33dcac1e Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 18 Oct 2023 17:25:29 -0400 Subject: [PATCH 4/7] Add changelog --- .changelog/33992.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/33992.txt diff --git a/.changelog/33992.txt b/.changelog/33992.txt new file mode 100644 index 00000000000..652fed9215f --- /dev/null +++ b/.changelog/33992.txt @@ -0,0 +1,3 @@ +```release-note:{HEADER} +resource/aws_lb: Add `dns_record_client_routing_policy` attribute to configure Availability Zonal DNS affinity on Network Load Balancer (NLB) +``` From d98370a6b5859381722401ce470804bd766502b1 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:19:40 -0400 Subject: [PATCH 5/7] Run testacc-lint-fix --- internal/service/elbv2/load_balancer_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index 44799da8965..89a8ac09c6f 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -2272,10 +2272,10 @@ resource "aws_subnet" "test" { func testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyAffinity(rName string) string { return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` resource "aws_lb" "test" { - name = %[1]q + name = %[1]q dns_record_client_routing_policy = "availability_zone_affinity" - internal = true - load_balancer_type = "network" + internal = true + load_balancer_type = "network" subnet_mapping { subnet_id = aws_subnet.test[0].id @@ -2291,10 +2291,10 @@ resource "aws_lb" "test" { func testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyAnyAvailabilityZone(rName string) string { return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` resource "aws_lb" "test" { - name = %[1]q + name = %[1]q dns_record_client_routing_policy = "any_availability_zone" - internal = true - load_balancer_type = "network" + internal = true + load_balancer_type = "network" subnet_mapping { subnet_id = aws_subnet.test[0].id @@ -2310,10 +2310,10 @@ resource "aws_lb" "test" { func testAccLoadBalancerConfig_nlbDNSRecordClientRoutingPolicyPartialAffinity(rName string) string { return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` resource "aws_lb" "test" { - name = %[1]q + name = %[1]q dns_record_client_routing_policy = "partial_availability_zone_affinity" - internal = true - load_balancer_type = "network" + internal = true + load_balancer_type = "network" subnet_mapping { subnet_id = aws_subnet.test[0].id From 51946114d0732c2789bd4a97124b6ef2bec2a739 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:21:27 -0400 Subject: [PATCH 6/7] Add docs --- website/docs/r/lb.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/r/lb.html.markdown b/website/docs/r/lb.html.markdown index c10368302c6..011686179ae 100644 --- a/website/docs/r/lb.html.markdown +++ b/website/docs/r/lb.html.markdown @@ -99,11 +99,12 @@ resource "aws_lb" "example" { ~> **NOTE:** Please note that one of either `subnets` or `subnet_mapping` is required. -This argument supports the following arguments: +This resource supports the following arguments: * `access_logs` - (Optional) An Access Logs block. Access Logs documented below. * `customer_owned_ipv4_pool` - (Optional) The ID of the customer owned ipv4 pool to use for this load balancer. * `desync_mitigation_mode` - (Optional) Determines how the load balancer handles requests that might pose a security risk to an application due to HTTP desync. Valid values are `monitor`, `defensive` (default), `strictest`. +* `dns_record_client_routing_policy` - (Optional) Indicates how traffic is distributed among the load balancer Availability Zones. Possible values are `any_availability_zone` (default), `availability_zone_affinity`, or `partial_availability_zone_affinity`. See [Availability Zone DNS affinity](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#zonal-dns-affinity) for additional details. Only valid for `network` type load balancers. * `drop_invalid_header_fields` - (Optional) Indicates whether HTTP headers with header fields that are not valid are removed by the load balancer (true) or routed to targets (false). The default is false. Elastic Load Balancing requires that message header names contain only alphanumeric characters and hyphens. Only valid for Load Balancers of type `application`. * `enable_cross_zone_load_balancing` - (Optional) If true, cross-zone load balancing of the load balancer will be enabled. For `network` and `gateway` type load balancers, this feature is disabled by default (`false`). For `application` load balancer this feature is always enabled (`true`) and cannot be disabled. Defaults to `false`. * `enable_deletion_protection` - (Optional) If true, deletion of the load balancer will be disabled via the AWS API. This will prevent Terraform from deleting the load balancer. Defaults to `false`. From 4d82b807c7910a4b82e37acdb55062391ebcc94d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 20 Oct 2023 12:11:09 -0400 Subject: [PATCH 7/7] Update 33992.txt --- .changelog/33992.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/33992.txt b/.changelog/33992.txt index 652fed9215f..d6eb2c9dbd7 100644 --- a/.changelog/33992.txt +++ b/.changelog/33992.txt @@ -1,3 +1,3 @@ -```release-note:{HEADER} +```release-note:enhancement resource/aws_lb: Add `dns_record_client_routing_policy` attribute to configure Availability Zonal DNS affinity on Network Load Balancer (NLB) ```