diff --git a/aws/resource_aws_lb.go b/aws/resource_aws_lb.go index f016ac09001..8834da8990f 100644 --- a/aws/resource_aws_lb.go +++ b/aws/resource_aws_lb.go @@ -21,7 +21,7 @@ import ( func resourceAwsLb() *schema.Resource { return &schema.Resource{ Create: resourceAwsLbCreate, - Read: resoureAwsLbRead, + Read: resourceAwsLbRead, Update: resourceAwsLbUpdate, Delete: resourceAwsLbDelete, // Subnets are ForceNew for Network Load Balancers @@ -157,6 +157,12 @@ func resourceAwsLb() *schema.Resource { Default: 60, }, + "enable_cross_zone_load_balancing": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "ip_address_type": { Type: schema.TypeString, Computed: true, @@ -247,7 +253,7 @@ func resourceAwsLbCreate(d *schema.ResourceData, meta interface{}) error { lb := resp.LoadBalancers[0] d.SetId(*lb.LoadBalancerArn) - log.Printf("[INFO] ALB ID: %s", d.Id()) + log.Printf("[INFO] LB ID: %s", d.Id()) stateConf := &resource.StateChangeConf{ Pending: []string{"provisioning", "failed"}, @@ -265,7 +271,7 @@ func resourceAwsLbCreate(d *schema.ResourceData, meta interface{}) error { } dLb := describeResp.LoadBalancers[0] - log.Printf("[INFO] ALB state: %s", *dLb.State.Code) + log.Printf("[INFO] LB state: %s", *dLb.State.Code) return describeResp, *dLb.State.Code, nil }, @@ -281,7 +287,7 @@ func resourceAwsLbCreate(d *schema.ResourceData, meta interface{}) error { return resourceAwsLbUpdate(d, meta) } -func resoureAwsLbRead(d *schema.ResourceData, meta interface{}) error { +func resourceAwsLbRead(d *schema.ResourceData, meta interface{}) error { elbconn := meta.(*AWSClient).elbv2conn lbArn := d.Id() @@ -362,6 +368,14 @@ func resourceAwsLbUpdate(d *schema.ResourceData, meta interface{}) error { }) } + // It's important to know that Idle timeout is only supported for Network Loadbalancers + if d.Get("load_balancer_type").(string) == "network" && d.HasChange("enable_cross_zone_load_balancing") { + 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))), + }) + } + if len(attributes) != 0 { input := &elbv2.ModifyLoadBalancerAttributesInput{ LoadBalancerArn: aws.String(d.Id()), @@ -371,7 +385,7 @@ func resourceAwsLbUpdate(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] ALB Modify Load Balancer Attributes Request: %#v", input) _, err := elbconn.ModifyLoadBalancerAttributes(input) if err != nil { - return fmt.Errorf("Failure configuring ALB attributes: %s", err) + return fmt.Errorf("Failure configuring LB attributes: %s", err) } } @@ -384,7 +398,7 @@ func resourceAwsLbUpdate(d *schema.ResourceData, meta interface{}) error { } _, err := elbconn.SetSecurityGroups(params) if err != nil { - return fmt.Errorf("Failure Setting ALB Security Groups: %s", err) + return fmt.Errorf("Failure Setting LB Security Groups: %s", err) } } @@ -403,7 +417,7 @@ func resourceAwsLbUpdate(d *schema.ResourceData, meta interface{}) error { _, err := elbconn.SetSubnets(params) if err != nil { - return fmt.Errorf("Failure Setting ALB Subnets: %s", err) + return fmt.Errorf("Failure Setting LB Subnets: %s", err) } } @@ -416,7 +430,7 @@ func resourceAwsLbUpdate(d *schema.ResourceData, meta interface{}) error { _, err := elbconn.SetIpAddressType(params) if err != nil { - return fmt.Errorf("Failure Setting ALB IP Address Type: %s", err) + return fmt.Errorf("Failure Setting LB IP Address Type: %s", err) } } @@ -437,7 +451,7 @@ func resourceAwsLbUpdate(d *schema.ResourceData, meta interface{}) error { } dLb := describeResp.LoadBalancers[0] - log.Printf("[INFO] ALB state: %s", *dLb.State.Code) + log.Printf("[INFO] LB state: %s", *dLb.State.Code) return describeResp, *dLb.State.Code, nil }, @@ -450,20 +464,20 @@ func resourceAwsLbUpdate(d *schema.ResourceData, meta interface{}) error { return err } - return resoureAwsLbRead(d, meta) + return resourceAwsLbRead(d, meta) } func resourceAwsLbDelete(d *schema.ResourceData, meta interface{}) error { lbconn := meta.(*AWSClient).elbv2conn - log.Printf("[INFO] Deleting ALB: %s", d.Id()) + log.Printf("[INFO] Deleting LB: %s", d.Id()) // Destroy the load balancer deleteElbOpts := elbv2.DeleteLoadBalancerInput{ LoadBalancerArn: aws.String(d.Id()), } if _, err := lbconn.DeleteLoadBalancer(&deleteElbOpts); err != nil { - return fmt.Errorf("Error deleting ALB: %s", err) + return fmt.Errorf("Error deleting LB: %s", err) } conn := meta.(*AWSClient).ec2conn @@ -642,7 +656,7 @@ func flattenAwsLbResource(d *schema.ResourceData, meta interface{}, lb *elbv2.Lo ResourceArns: []*string{lb.LoadBalancerArn}, }) if err != nil { - return errwrap.Wrapf("Error retrieving ALB Tags: {{err}}", err) + return errwrap.Wrapf("Error retrieving LB Tags: {{err}}", err) } var et []*elbv2.Tag @@ -658,7 +672,7 @@ func flattenAwsLbResource(d *schema.ResourceData, meta interface{}, lb *elbv2.Lo LoadBalancerArn: aws.String(d.Id()), }) if err != nil { - return errwrap.Wrapf("Error retrieving ALB Attributes: {{err}}", err) + return errwrap.Wrapf("Error retrieving LB Attributes: {{err}}", err) } accessLogMap := map[string]interface{}{} @@ -679,8 +693,12 @@ func flattenAwsLbResource(d *schema.ResourceData, meta interface{}, lb *elbv2.Lo d.Set("idle_timeout", timeout) case "deletion_protection.enabled": protectionEnabled := (*attr.Value) == "true" - log.Printf("[DEBUG] Setting ALB Deletion Protection Enabled: %t", protectionEnabled) + log.Printf("[DEBUG] Setting LB Deletion Protection Enabled: %t", protectionEnabled) d.Set("enable_deletion_protection", protectionEnabled) + case "load_balancing.cross_zone.enabled": + crossZoneLbEnabled := (*attr.Value) == "true" + log.Printf("[DEBUG] Setting NLB Cross Zone Load Balancing Enabled: %t", crossZoneLbEnabled) + d.Set("enable_cross_zone_load_balancing", crossZoneLbEnabled) } } diff --git a/aws/resource_aws_lb_test.go b/aws/resource_aws_lb_test.go index 19068f1b603..8ed851df4ee 100644 --- a/aws/resource_aws_lb_test.go +++ b/aws/resource_aws_lb_test.go @@ -79,7 +79,7 @@ func TestAccAWSLB_basic(t *testing.T) { }) } -func TestAccAWSLB_networkLoadbalancer(t *testing.T) { +func TestAccAWSLB_networkLoadbalancerBasic(t *testing.T) { var conf elbv2.LoadBalancer lbName := fmt.Sprintf("testaccawslb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) @@ -90,7 +90,7 @@ func TestAccAWSLB_networkLoadbalancer(t *testing.T) { CheckDestroy: testAccCheckAWSLBDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLBConfig_networkLoadbalancer(lbName), + Config: testAccAWSLBConfig_networkLoadbalancer(lbName, false), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSLBExists("aws_lb.lb_test", &conf), resource.TestCheckResourceAttr("aws_lb.lb_test", "name", lbName), @@ -128,6 +128,7 @@ func TestAccAWSLB_networkLoadbalancerEIP(t *testing.T) { resource.TestCheckResourceAttrSet("aws_lb.test", "zone_id"), resource.TestCheckResourceAttrSet("aws_lb.test", "dns_name"), resource.TestCheckResourceAttrSet("aws_lb.test", "arn"), + resource.TestCheckResourceAttr("aws_lb.test", "enable_cross_zone_load_balancing", "true"), resource.TestCheckResourceAttr("aws_lb.test", "load_balancer_type", "network"), resource.TestCheckResourceAttr("aws_lb.test", "subnet_mapping.#", "2"), ), @@ -157,6 +158,7 @@ func TestAccAWSLBBackwardsCompatibility(t *testing.T) { resource.TestCheckResourceAttr("aws_alb.lb_test", "tags.%", "1"), resource.TestCheckResourceAttr("aws_alb.lb_test", "tags.Name", "TestAccAWSALB_basic"), resource.TestCheckResourceAttr("aws_alb.lb_test", "enable_deletion_protection", "false"), + resource.TestCheckResourceAttr("aws_alb.lb_test", "enable_cross_zone_load_balancing", "false"), resource.TestCheckResourceAttr("aws_alb.lb_test", "idle_timeout", "30"), resource.TestCheckResourceAttr("aws_alb.lb_test", "ip_address_type", "ipv4"), resource.TestCheckResourceAttr("aws_alb.lb_test", "load_balancer_type", "application"), @@ -263,6 +265,35 @@ func TestAccAWSLB_tags(t *testing.T) { }) } +func TestAccAWSLB_networkLoadbalancer_updateCrossZone(t *testing.T) { + var pre, post elbv2.LoadBalancer + lbName := fmt.Sprintf("testaccawslb-nlbcz-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_lb.lb_test", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLBDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLBConfig_networkLoadbalancer(lbName, true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLBExists("aws_lb.lb_test", &pre), + resource.TestCheckResourceAttr("aws_lb.lb_test", "enable_cross_zone_load_balancing", "true"), + ), + }, + { + Config: testAccAWSLBConfig_networkLoadbalancer(lbName, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLBExists("aws_lb.lb_test", &post), + resource.TestCheckResourceAttr("aws_lb.lb_test", "enable_cross_zone_load_balancing", "false"), + testAccCheckAWSlbARNs(&pre, &post), + ), + }, + }, + }) +} + func TestAccAWSLB_updatedSecurityGroups(t *testing.T) { var pre, post elbv2.LoadBalancer lbName := fmt.Sprintf("testaccawslb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) @@ -861,10 +892,11 @@ resource "aws_lb" "lb_test" { "${aws_subnet.alb_test_3.id}", ] - load_balancer_type = "network" - internal = true - idle_timeout = 60 - enable_deletion_protection = false + load_balancer_type = "network" + internal = true + idle_timeout = 60 + enable_deletion_protection = false + enable_cross_zone_load_balancing = false tags { Name = "testAccAWSLBConfig_networkLoadbalancer_subnets" @@ -902,13 +934,15 @@ resource "aws_subnet" "alb_test_3" { } `, lbName) } -func testAccAWSLBConfig_networkLoadbalancer(lbName string) string { + +func testAccAWSLBConfig_networkLoadbalancer(lbName string, cz bool) string { return fmt.Sprintf(`resource "aws_lb" "lb_test" { name = "%s" internal = true load_balancer_type = "network" - enable_deletion_protection = false + enable_deletion_protection = false + enable_cross_zone_load_balancing = %t subnet_mapping { subnet_id = "${aws_subnet.alb_test.id}" @@ -938,7 +972,7 @@ resource "aws_subnet" "alb_test" { } } -`, lbName) +`, lbName, cz) } func testAccAWSLBConfig_networkLoadBalancerEIP(lbName string) string { @@ -980,6 +1014,7 @@ resource "aws_route_table_association" "a" { resource "aws_lb" "test" { name = "%s" load_balancer_type = "network" + enable_cross_zone_load_balancing = true subnet_mapping { subnet_id = "${aws_subnet.public.0.id}" allocation_id = "${aws_eip.lb.0.id}" diff --git a/website/docs/r/lb.html.markdown b/website/docs/r/lb.html.markdown index 9f86108d1eb..3e2bcb1cf5d 100644 --- a/website/docs/r/lb.html.markdown +++ b/website/docs/r/lb.html.markdown @@ -60,6 +60,8 @@ will for load balancers of type `network` will force a recreation of the resourc * `idle_timeout` - (Optional) The time in seconds that the connection is allowed to be idle. Default: 60. * `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`. +* `enable_cross_zone_load_balancing` - (Optional) If true, cross-zone load balancing of the load balancer will be enabled. + This is a `network` load balancer feature. Defaults to `false`. * `ip_address_type` - (Optional) The type of IP addresses used by the subnets for your load balancer. The possible values are `ipv4` and `dualstack` * `tags` - (Optional) A mapping of tags to assign to the resource.