diff --git a/aws/data_source_aws_lb_target_group.go b/aws/data_source_aws_lb_target_group.go index 0b2b94a3211..b22e4bc98db 100644 --- a/aws/data_source_aws_lb_target_group.go +++ b/aws/data_source_aws_lb_target_group.go @@ -40,6 +40,11 @@ func dataSourceAwsLbTargetGroup() *schema.Resource { Computed: true, }, + "protocol_version": { + Type: schema.TypeString, + Computed: true, + }, + "vpc_id": { Type: schema.TypeString, Computed: true, diff --git a/aws/data_source_aws_lb_target_group_test.go b/aws/data_source_aws_lb_target_group_test.go index 561c52666bf..56f00d7b7c6 100644 --- a/aws/data_source_aws_lb_target_group_test.go +++ b/aws/data_source_aws_lb_target_group_test.go @@ -26,6 +26,7 @@ func TestAccDataSourceAWSALBTargetGroup_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceNameArn, "arn_suffix"), resource.TestCheckResourceAttr(resourceNameArn, "port", "8080"), resource.TestCheckResourceAttr(resourceNameArn, "protocol", "HTTP"), + resource.TestCheckResourceAttr(resourceNameArn, "protocol_version", "HTTP1"), resource.TestCheckResourceAttrSet(resourceNameArn, "vpc_id"), resource.TestCheckResourceAttrSet(resourceNameArn, "load_balancing_algorithm_type"), resource.TestCheckResourceAttr(resourceNameArn, "deregistration_delay", "300"), diff --git a/aws/resource_aws_lb_target_group.go b/aws/resource_aws_lb_target_group.go index 2103b85b3a0..cfaf1bade91 100644 --- a/aws/resource_aws_lb_target_group.go +++ b/aws/resource_aws_lb_target_group.go @@ -72,6 +72,20 @@ func resourceAwsLbTargetGroup() *schema.Resource { ValidateFunc: validation.StringInSlice(elbv2.ProtocolEnum_Values(), true), }, + "protocol_version": { + Type: schema.TypeString, + Optional: true, + Computed: true, + StateFunc: func(v interface{}) string { + return strings.ToUpper(v.(string)) + }, + ValidateFunc: validation.StringInSlice([]string{ + "HTTP1", + "HTTP2", + "GRPC", + }, true), + }, + "vpc_id": { Type: schema.TypeString, Optional: true, @@ -294,6 +308,10 @@ func resourceAwsLbTargetGroupCreate(d *schema.ResourceData, meta interface{}) er } params.Port = aws.Int64(int64(d.Get("port").(int))) params.Protocol = aws.String(d.Get("protocol").(string)) + switch d.Get("protocol").(string) { + case elbv2.ProtocolEnumHttp, elbv2.ProtocolEnumHttps: + params.ProtocolVersion = aws.String(d.Get("protocol_version").(string)) + } params.VpcId = aws.String(d.Get("vpc_id").(string)) } @@ -632,6 +650,10 @@ func flattenAwsLbTargetGroupResource(d *schema.ResourceData, meta interface{}, t d.Set("port", targetGroup.Port) d.Set("protocol", targetGroup.Protocol) } + switch d.Get("protocol").(string) { + case elbv2.ProtocolEnumHttp, elbv2.ProtocolEnumHttps: + d.Set("protocol_version", targetGroup.ProtocolVersion) + } if err := d.Set("health_check", []interface{}{healthCheck}); err != nil { return fmt.Errorf("error setting health_check: %s", err) @@ -727,7 +749,7 @@ func flattenAwsLbTargetGroupStickiness(d *schema.ResourceData, attributes []*elb func resourceAwsLbTargetGroupCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v interface{}) error { protocol := diff.Get("protocol").(string) - // Network Load Balancers have many special qwirks to them. + // Network Load Balancers have many special quirks to them. // See http://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_CreateTargetGroup.html if healthChecks := diff.Get("health_check").([]interface{}); len(healthChecks) == 1 { healthCheck := healthChecks[0].(map[string]interface{}) diff --git a/aws/resource_aws_lb_target_group_test.go b/aws/resource_aws_lb_target_group_test.go index 34e4f3dfc61..171b5897b25 100644 --- a/aws/resource_aws_lb_target_group_test.go +++ b/aws/resource_aws_lb_target_group_test.go @@ -110,6 +110,7 @@ func TestAccAWSLBTargetGroup_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "name", targetGroupName), resource.TestCheckResourceAttr(resourceName, "port", "443"), resource.TestCheckResourceAttr(resourceName, "protocol", "HTTPS"), + resource.TestCheckResourceAttr(resourceName, "protocol_version", "HTTP1"), resource.TestCheckResourceAttrSet(resourceName, "vpc_id"), resource.TestCheckResourceAttr(resourceName, "deregistration_delay", "200"), resource.TestCheckResourceAttr(resourceName, "slow_start", "0"), @@ -166,6 +167,51 @@ func TestAccAWSLBTargetGroup_basicUdp(t *testing.T) { }) } +func TestAccAWSLBTargetGroup_ProtocolVersion(t *testing.T) { + var conf elbv2.TargetGroup + targetGroupName := fmt.Sprintf("test-target-group-%s", acctest.RandString(10)) + resourceName := "aws_lb_target_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: resourceName, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLBTargetGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLBTargetGroupConfig_ProtocolVersion(targetGroupName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSLBTargetGroupExists(resourceName, &conf), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "name", targetGroupName), + resource.TestCheckResourceAttr(resourceName, "port", "443"), + resource.TestCheckResourceAttr(resourceName, "protocol", "HTTPS"), + resource.TestCheckResourceAttr(resourceName, "protocol_version", "HTTP2"), + resource.TestCheckResourceAttrSet(resourceName, "vpc_id"), + resource.TestCheckResourceAttr(resourceName, "deregistration_delay", "200"), + resource.TestCheckResourceAttr(resourceName, "slow_start", "0"), + resource.TestCheckResourceAttr(resourceName, "stickiness.#", "1"), + resource.TestCheckResourceAttr(resourceName, "stickiness.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "stickiness.0.type", "lb_cookie"), + resource.TestCheckResourceAttr(resourceName, "stickiness.0.cookie_duration", "10000"), + resource.TestCheckResourceAttr(resourceName, "health_check.#", "1"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.path", "/health"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.interval", "60"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.port", "8081"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.protocol", "HTTP"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.timeout", "3"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.healthy_threshold", "3"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.unhealthy_threshold", "3"), + resource.TestCheckResourceAttr(resourceName, "health_check.0.matcher", "200-299"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", "TestAccAWSLBTargetGroup_basic"), + ), + }, + }, + }) +} + func TestAccAWSLBTargetGroup_withoutHealthcheck(t *testing.T) { var conf elbv2.TargetGroup targetGroupName := fmt.Sprintf("test-target-group-%s", acctest.RandString(10)) @@ -1466,6 +1512,49 @@ resource "aws_vpc" "test" { `, targetGroupName) } +func testAccAWSLBTargetGroupConfig_ProtocolVersion(targetGroupName string) string { + return fmt.Sprintf(` +resource "aws_lb_target_group" "test" { + name = "%s" + port = 443 + protocol = "HTTPS" + protocol_version = "HTTP2" + vpc_id = aws_vpc.test.id + + deregistration_delay = 200 + slow_start = 0 + + stickiness { + type = "lb_cookie" + cookie_duration = 10000 + } + + health_check { + path = "/health" + interval = 60 + port = 8081 + protocol = "HTTP" + timeout = 3 + healthy_threshold = 3 + unhealthy_threshold = 3 + matcher = "200-299" + } + + tags = { + Name = "TestAccAWSLBTargetGroup_basic" + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = "terraform-testacc-lb-target-group-basic" + } +} +`, targetGroupName) +} + func testAccAWSLBTargetGroupConfigProtocolGeneve(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { diff --git a/website/docs/r/lb_target_group.html.markdown b/website/docs/r/lb_target_group.html.markdown index e41d4f980c9..8e9a37e23f2 100644 --- a/website/docs/r/lb_target_group.html.markdown +++ b/website/docs/r/lb_target_group.html.markdown @@ -63,6 +63,7 @@ The following arguments are supported: * `port` - (Optional, Forces new resource) The port on which targets receive traffic, unless overridden when registering a specific target. Required when `target_type` is `instance` or `ip`. Does not apply when `target_type` is `lambda`. * `protocol` - (Optional, Forces new resource) The protocol to use for routing traffic to the targets. Should be one of `GENEVE`, `HTTP`, `HTTPS`, `TCP`, `TCP_UDP`, `TLS`, or `UDP`. Required when `target_type` is `instance` or `ip`. Does not apply when `target_type` is `lambda`. +* `protocol_version` - (Optional, Forces new resource) Only applicable when `protocol` is `HTTP` or `HTTPS`. The protocol version. Specify GRPC to send requests to targets using gRPC. Specify HTTP2 to send requests to targets using HTTP/2. The default is HTTP1, which sends requests to targets using HTTP/1.1 * `vpc_id` - (Optional, Forces new resource) The identifier of the VPC in which to create the target group. Required when `target_type` is `instance` or `ip`. Does not apply when `target_type` is `lambda`. * `deregistration_delay` - (Optional) The amount time for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds. * `slow_start` - (Optional) The amount time for targets to warm up before the load balancer sends them a full share of requests. The range is 30-900 seconds or 0 to disable. The default value is 0 seconds.