Skip to content

Commit

Permalink
Merge pull request #33994 from ddericco/f-aws_lb-nlb_dns_client_routi…
Browse files Browse the repository at this point in the history
…ng_policy

Add support for Availability Zonal DNS affinity on NLB
  • Loading branch information
ewbankkit authored Oct 20, 2023
2 parents 9b2d692 + 4d82b80 commit e1dadb4
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .changelog/33992.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_lb: Add `dns_record_client_routing_policy` attribute to configure Availability Zonal DNS affinity on Network Load Balancer (NLB)
```
31 changes: 30 additions & 1 deletion internal/service/elbv2/load_balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@ func ResourceLoadBalancer() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"dns_record_client_routing_policy": {
Type: schema.TypeString,
Optional: true,
Default: "any_availability_zone",
DiffSuppressFunc: suppressIfLBTypeNot(elbv2.LoadBalancerTypeEnumNetwork),
ValidateFunc: validation.StringInSlice([]string{
"availability_zone_affinity",
"partial_availability_zone_affinity",
"any_availability_zone",
}, false),
},
"drop_invalid_header_fields": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -523,7 +534,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"),
Expand Down Expand Up @@ -952,6 +977,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 {
Expand Down
100 changes: 100 additions & 0 deletions internal/service/elbv2/load_balancer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,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"),
Expand Down Expand Up @@ -1329,6 +1330,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
Expand Down Expand Up @@ -2323,6 +2366,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" {
Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/lb.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down

0 comments on commit e1dadb4

Please sign in to comment.