From dd462fb0e3d33e8be9927059d1f0b85f6595f164 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Thu, 19 Nov 2020 01:43:55 -0500 Subject: [PATCH 1/2] resource/aws_lb_listener: Mark port argument as optional and only default protocol argument to HTTP for Application Load Balancers (Support Gateway Load Balancer) Reference: https://github.com/hashicorp/terraform-provider-aws/issues/16228 Output from acceptance testing: ``` --- PASS: TestAccAWSLBListener_BackwardsCompatibility (164.54s) --- PASS: TestAccAWSLBListener_basic (216.95s) --- PASS: TestAccAWSLBListener_basicUdp (353.16s) --- PASS: TestAccAWSLBListener_cognito (175.47s) --- PASS: TestAccAWSLBListener_DefaultAction_Order (179.98s) --- PASS: TestAccAWSLBListener_DefaultAction_Order_Recreates (210.11s) --- PASS: TestAccAWSLBListener_fixedResponse (205.74s) --- PASS: TestAccAWSLBListener_forwardWeighted (254.29s) --- PASS: TestAccAWSLBListener_https (177.85s) --- PASS: TestAccAWSLBListener_LoadBalancerArn_GatewayLoadBalancer (104.60s) --- PASS: TestAccAWSLBListener_oidc (224.41s) --- PASS: TestAccAWSLBListener_Protocol_Tls (338.84s) --- PASS: TestAccAWSLBListener_redirect (215.20s) --- PASS: TestAccAWSLBListenerRule_Action_Order (173.51s) --- PASS: TestAccAWSLBListenerRule_Action_Order_Recreates (190.92s) --- PASS: TestAccAWSLBListenerRule_BackwardsCompatibility (215.63s) --- PASS: TestAccAWSLBListenerRule_basic (205.27s) --- PASS: TestAccAWSLBListenerRule_changeListenerRuleArnForcesNew (241.13s) --- PASS: TestAccAWSLBListenerRule_cognito (204.34s) --- PASS: TestAccAWSLBListenerRule_conditionAttributesCount (14.00s) --- PASS: TestAccAWSLBListenerRule_conditionHostHeader (213.13s) --- PASS: TestAccAWSLBListenerRule_conditionHttpHeader (258.35s) --- PASS: TestAccAWSLBListenerRule_conditionHttpHeader_invalid (0.56s) --- PASS: TestAccAWSLBListenerRule_conditionHttpRequestMethod (180.34s) --- PASS: TestAccAWSLBListenerRule_conditionMultiple (193.68s) --- PASS: TestAccAWSLBListenerRule_conditionPathPattern (205.29s) --- PASS: TestAccAWSLBListenerRule_conditionQueryString (245.64s) --- PASS: TestAccAWSLBListenerRule_conditionSourceIp (203.60s) --- PASS: TestAccAWSLBListenerRule_conditionUpdateMixed (239.41s) --- PASS: TestAccAWSLBListenerRule_conditionUpdateMultiple (174.24s) --- PASS: TestAccAWSLBListenerRule_fixedResponse (244.72s) --- PASS: TestAccAWSLBListenerRule_forwardWeighted (298.68s) --- PASS: TestAccAWSLBListenerRule_oidc (226.14s) --- PASS: TestAccAWSLBListenerRule_priority (352.95s) --- PASS: TestAccAWSLBListenerRule_redirect (162.81s) --- PASS: TestAccAWSLBListenerRule_updateFixedResponse (233.36s) --- PASS: TestAccAWSLBListenerRule_updateRulePriority (204.08s) ``` --- aws/resource_aws_lb_listener.go | 36 ++++++----- aws/resource_aws_lb_listener_test.go | 79 +++++++++++++++++++++++- website/docs/r/lb_listener.html.markdown | 37 ++++++++++- 3 files changed, 135 insertions(+), 17 deletions(-) diff --git a/aws/resource_aws_lb_listener.go b/aws/resource_aws_lb_listener.go index 8fc14d26d45..132efa93dfa 100644 --- a/aws/resource_aws_lb_listener.go +++ b/aws/resource_aws_lb_listener.go @@ -45,25 +45,18 @@ func resourceAwsLbListener() *schema.Resource { "port": { Type: schema.TypeInt, - Required: true, + Optional: true, ValidateFunc: validation.IntBetween(1, 65535), }, "protocol": { Type: schema.TypeString, Optional: true, - Default: "HTTP", + Computed: true, StateFunc: func(v interface{}) string { return strings.ToUpper(v.(string)) }, - ValidateFunc: validation.StringInSlice([]string{ - elbv2.ProtocolEnumHttp, - elbv2.ProtocolEnumHttps, - elbv2.ProtocolEnumTcp, - elbv2.ProtocolEnumTls, - elbv2.ProtocolEnumUdp, - elbv2.ProtocolEnumTcpUdp, - }, true), + ValidateFunc: validation.StringInSlice(elbv2.ProtocolEnum_Values(), true), }, "ssl_policy": { @@ -392,8 +385,17 @@ func resourceAwsLbListenerCreate(d *schema.ResourceData, meta interface{}) error params := &elbv2.CreateListenerInput{ LoadBalancerArn: aws.String(lbArn), - Port: aws.Int64(int64(d.Get("port").(int))), - Protocol: aws.String(d.Get("protocol").(string)), + } + + if v, ok := d.GetOk("port"); ok { + params.Port = aws.Int64(int64(v.(int))) + } + + if v, ok := d.GetOk("protocol"); ok { + params.Protocol = aws.String(v.(string)) + } else if strings.Contains(lbArn, "loadbalancer/app/") { + // Keep previous default of HTTP for Application Load Balancers + params.Protocol = aws.String(elbv2.ProtocolEnumHttp) } if sslPolicy, ok := d.GetOk("ssl_policy"); ok { @@ -744,8 +746,14 @@ func resourceAwsLbListenerUpdate(d *schema.ResourceData, meta interface{}) error params := &elbv2.ModifyListenerInput{ ListenerArn: aws.String(d.Id()), - Port: aws.Int64(int64(d.Get("port").(int))), - Protocol: aws.String(d.Get("protocol").(string)), + } + + if v, ok := d.GetOk("port"); ok { + params.Port = aws.Int64(int64(v.(int))) + } + + if v, ok := d.GetOk("protocol"); ok { + params.Protocol = aws.String(v.(string)) } if sslPolicy, ok := d.GetOk("ssl_policy"); ok { diff --git a/aws/resource_aws_lb_listener_test.go b/aws/resource_aws_lb_listener_test.go index b271acd76d1..7149f8f0c04 100644 --- a/aws/resource_aws_lb_listener_test.go +++ b/aws/resource_aws_lb_listener_test.go @@ -213,6 +213,30 @@ func TestAccAWSLBListener_https(t *testing.T) { }) } +func TestAccAWSLBListener_LoadBalancerArn_GatewayLoadBalancer(t *testing.T) { + var conf elbv2.Listener + rName := acctest.RandomWithPrefix("tf-acc-test") + lbResourceName := "aws_lb.test" + resourceName := "aws_lb_listener.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLBListenerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLBListenerConfig_LoadBalancerArn_GatewayLoadBalancer(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLBListenerExists(resourceName, &conf), + resource.TestCheckResourceAttrPair(resourceName, "load_balancer_arn", lbResourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "protocol", ""), + resource.TestCheckResourceAttr(resourceName, "port", "0"), + ), + }, + }, + }) +} + func TestAccAWSLBListener_Protocol_Tls(t *testing.T) { var listener1 elbv2.Listener key := tlsRsaPrivateKeyPem(2048) @@ -528,7 +552,6 @@ func testAccAWSLBListenerConfig_basic(lbName, targetGroupName string) string { return fmt.Sprintf(` resource "aws_lb_listener" "front_end" { load_balancer_arn = aws_lb.alb_test.id - protocol = "HTTP" port = "80" default_action { @@ -1336,6 +1359,60 @@ resource "aws_iam_server_certificate" "test_cert" { `, rName, tlsPemEscapeNewlines(certificate), tlsPemEscapeNewlines(key)) } +func testAccAWSLBListenerConfig_LoadBalancerArn_GatewayLoadBalancer(rName string) string { + return composeConfig( + testAccAvailableAZsNoOptInConfig(), + fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.10.10.0/25" + + tags = { + Name = "tf-acc-test-load-balancer" + } +} + +resource "aws_subnet" "test" { + availability_zone = data.aws_availability_zones.available.names[0] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 2, 0) + vpc_id = aws_vpc.test.id + + tags = { + Name = "tf-acc-test-load-balancer" + } +} + +resource "aws_lb" "test" { + load_balancer_type = "gateway" + name = %[1]q + + subnet_mapping { + subnet_id = aws_subnet.test.id + } +} + +resource "aws_lb_target_group" "test" { + name = %[1]q + port = 6081 + protocol = "GENEVE" + vpc_id = aws_vpc.test.id + + health_check { + port = 80 + protocol = "HTTP" + } +} + +resource "aws_lb_listener" "test" { + load_balancer_arn = aws_lb.test.id + + default_action { + target_group_arn = aws_lb_target_group.test.id + type = "forward" + } +} +`, rName)) +} + func testAccAWSLBListenerConfig_Protocol_Tls(rName, key, certificate string) string { return fmt.Sprintf(` data "aws_availability_zones" "available" { diff --git a/website/docs/r/lb_listener.html.markdown b/website/docs/r/lb_listener.html.markdown index b374e0c88ae..e34be1304f0 100644 --- a/website/docs/r/lb_listener.html.markdown +++ b/website/docs/r/lb_listener.html.markdown @@ -168,14 +168,47 @@ resource "aws_lb_listener" "front_end" { } ``` +### Gateway Load Balancer Listener + +```hcl +resource "aws_lb" "example" { + load_balancer_type = "gateway" + name = "example" + + subnet_mapping { + subnet_id = aws_subnet.example.id + } +} + +resource "aws_lb_target_group" "example" { + name = "example" + port = 6081 + protocol = "GENEVE" + vpc_id = aws_vpc.example.id + + health_check { + port = 80 + protocol = "HTTP" + } +} + +resource "aws_lb_listener" "example" { + load_balancer_arn = aws_lb.example.id + + default_action { + target_group_arn = aws_lb_target_group.example.id + type = "forward" + } +} +``` ## Argument Reference The following arguments are supported: * `load_balancer_arn` - (Required, Forces New Resource) The ARN of the load balancer. -* `port` - (Required) The port on which the load balancer is listening. -* `protocol` - (Optional) The protocol for connections from clients to the load balancer. Valid values are `TCP`, `TLS`, `UDP`, `TCP_UDP`, `HTTP` and `HTTPS`. Defaults to `HTTP`. +* `port` - (Optional) The port on which the load balancer is listening. Not valid for Gateway Load Balancers. +* `protocol` - (Optional) The protocol for connections from clients to the load balancer. For Application Load Balancers, valid values are `HTTP` and `HTTPS`, with a default of `HTTP`. For Network Load Balancers, valid values are `TCP`, `TLS`, `UDP`, and `TCP_UDP`. Not valid to use `UDP` or `TCP_UDP` if dual-stack mode is enabled. Not valid for Gateway Load Balancers. * `ssl_policy` - (Optional) The name of the SSL Policy for the listener. Required if `protocol` is `HTTPS` or `TLS`. * `certificate_arn` - (Optional) The ARN of the default SSL server certificate. Exactly one certificate is required if the protocol is HTTPS. For adding additional SSL certificates, see the [`aws_lb_listener_certificate` resource](/docs/providers/aws/r/lb_listener_certificate.html). * `default_action` - (Required) An Action block. Action blocks are documented below. From e122cadd549127a2340c94ae735e095c3ad0164d Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Thu, 19 Nov 2020 09:59:36 -0500 Subject: [PATCH 2/2] tests/provider: Ignore out of date tflint rules aws_lb_invalid_load_balancer_type and aws_lb_target_group_invalid_protocol Reference: https://github.com/terraform-linters/tflint/issues/975 --- .github/workflows/website.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 9c1a3d211e3..d3729248912 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -109,6 +109,8 @@ jobs: "--disable-rule=aws_iam_saml_provider_invalid_saml_metadata_document" "--disable-rule=aws_iam_server_certificate_invalid_certificate_body" "--disable-rule=aws_iam_server_certificate_invalid_private_key" + "--disable-rule=aws_lb_invalid_load_balancer_type" + "--disable-rule=aws_lb_target_group_invalid_protocol" "--disable-rule=aws_transfer_ssh_key_invalid_body" "--disable-rule=aws_worklink_website_certificate_authority_association_invalid_certificate" )