Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add protocol_version to lb target groups #16132

Closed
55 changes: 47 additions & 8 deletions aws/resource_aws_lb_target_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ func resourceAwsLbTargetGroup() *schema.Resource {
"protocol_version": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: "HTTP1",
Computed: true,
StateFunc: func(v interface{}) string {
return strings.ToUpper(v.(string))
Expand All @@ -84,6 +86,16 @@ func resourceAwsLbTargetGroup() *schema.Resource {
"HTTP2",
"GRPC",
}, true),
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if d.Get("target_type").(string) == elbv2.TargetTypeEnumLambda {
return true
}
switch d.Get("protocol").(string) {
case elbv2.ProtocolEnumHttp, elbv2.ProtocolEnumHttps:
return false
}
return true
},
},

"vpc_id": {
Expand Down Expand Up @@ -306,12 +318,22 @@ func resourceAwsLbTargetGroupCreate(d *schema.ResourceData, meta interface{}) er
if _, ok := d.GetOk("vpc_id"); !ok {
return fmt.Errorf("vpc_id should be set when target type is %s", d.Get("target_type").(string))
}

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))

if d.Get("protocol").(string) == "HTTP" || d.Get("protocol").(string) == "HTTPS" {
if _, ok := d.GetOk("protocol_version"); ok {
params.ProtocolVersion = aws.String(d.Get("protocol_version").(string))
} else {
params.ProtocolVersion = aws.String("HTTP1")
}
} else {
if _, ok := d.GetOk("protocol_version"); ok {
return fmt.Errorf("protocol_version should not be set when protocol is %s", d.Get("protocol").(string))
}
}

params.VpcId = aws.String(d.Get("vpc_id").(string))
}

Expand All @@ -337,9 +359,16 @@ func resourceAwsLbTargetGroupCreate(d *schema.ResourceData, meta interface{}) er
}

m := healthCheck["matcher"].(string)
protocolVersion := d.Get("protocol_version").(string)
if m != "" {
params.Matcher = &elbv2.Matcher{
HttpCode: aws.String(m),
if protocolVersion == "GRPC" {
params.Matcher = &elbv2.Matcher{
GrpcCode: aws.String(m),
}
} else {
params.Matcher = &elbv2.Matcher{
HttpCode: aws.String(m),
}
}
}
}
Expand Down Expand Up @@ -416,10 +445,16 @@ func resourceAwsLbTargetGroupUpdate(d *schema.ResourceData, meta interface{}) er
}

healthCheckProtocol := healthCheck["protocol"].(string)

protocolVersion := d.Get("protocol_version").(string)
if healthCheckProtocol != elbv2.ProtocolEnumTcp && !d.IsNewResource() {
params.Matcher = &elbv2.Matcher{
HttpCode: aws.String(healthCheck["matcher"].(string)),
if protocolVersion == "GRPC" {
params.Matcher = &elbv2.Matcher{
GrpcCode: aws.String(healthCheck["matcher"].(string)),
}
} else {
params.Matcher = &elbv2.Matcher{
HttpCode: aws.String(healthCheck["matcher"].(string)),
}
}
params.HealthCheckPath = aws.String(healthCheck["path"].(string))
params.HealthCheckIntervalSeconds = aws.Int64(int64(healthCheck["interval"].(int)))
Expand Down Expand Up @@ -645,10 +680,14 @@ func flattenAwsLbTargetGroupResource(d *schema.ResourceData, meta interface{}, t
if targetGroup.Matcher != nil && targetGroup.Matcher.HttpCode != nil {
healthCheck["matcher"] = aws.StringValue(targetGroup.Matcher.HttpCode)
}
if targetGroup.Matcher != nil && targetGroup.Matcher.GrpcCode != nil {
healthCheck["matcher"] = aws.StringValue(targetGroup.Matcher.GrpcCode)
}
if v, _ := d.Get("target_type").(string); v != elbv2.TargetTypeEnumLambda {
d.Set("vpc_id", targetGroup.VpcId)
d.Set("port", targetGroup.Port)
d.Set("protocol", targetGroup.Protocol)
d.Set("protocol_version", targetGroup.ProtocolVersion)
}
switch d.Get("protocol").(string) {
case elbv2.ProtocolEnumHttp, elbv2.ProtocolEnumHttps:
Expand Down
105 changes: 105 additions & 0 deletions aws/resource_aws_lb_target_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,60 @@ func TestAccAWSLBTargetGroup_Protocol_Tls(t *testing.T) {
})
}

func TestAccAWSLBTargetGroup_ProtocolVersion_GRPC_HealthCheck(t *testing.T) {
var targetGroup1 elbv2.TargetGroup
targetGroupName := fmt.Sprintf("test-target-group-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
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_GRPC_ProtocolVersion(targetGroupName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSLBTargetGroupExists(resourceName, &targetGroup1),
resource.TestCheckResourceAttr(resourceName, "health_check.#", "1"),
resource.TestCheckResourceAttr(resourceName, "health_check.0.path", "/Test.Check/healthcheck"),
resource.TestCheckResourceAttr(resourceName, "health_check.0.matcher", "0-99"),
),
},
},
})
}

func TestAccAWSLBTargetGroup_ProtocolVersion_HTTP_GRPC_Update(t *testing.T) {
var targetGroup1 elbv2.TargetGroup
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_lb_target_group.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSLBTargetGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSLBTargetGroupConfig_basic(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSLBTargetGroupExists(resourceName, &targetGroup1),
resource.TestCheckResourceAttr(resourceName, "protocol", "HTTPS"),
resource.TestCheckResourceAttr(resourceName, "protocol_version", "HTTP1"),
),
},
{
Config: testAccAWSLBTargetGroupConfig_GRPC_ProtocolVersion(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSLBTargetGroupExists(resourceName, &targetGroup1),
resource.TestCheckResourceAttr(resourceName, "protocol", "HTTP"),
resource.TestCheckResourceAttr(resourceName, "protocol_version", "GRPC"),
),
},
},
})
}

func TestAccAWSLBTargetGroup_networkLB_TargetGroupWithProxy(t *testing.T) {
var confBefore, confAfter elbv2.TargetGroup
targetGroupName := fmt.Sprintf("test-target-group-%s", acctest.RandString(10))
Expand Down Expand Up @@ -952,6 +1006,7 @@ func TestAccAWSLBTargetGroup_defaults_application(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "name", targetGroupName),
resource.TestCheckResourceAttr(resourceName, "port", "443"),
resource.TestCheckResourceAttr(resourceName, "protocol", "HTTP"),
resource.TestCheckResourceAttr(resourceName, "protocol_version", "HTTP1"),
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
resource.TestCheckResourceAttr(resourceName, "deregistration_delay", "200"),
resource.TestCheckResourceAttr(resourceName, "slow_start", "0"),
Expand Down Expand Up @@ -1847,6 +1902,56 @@ resource "aws_vpc" "test" {
`, targetGroupName)
}

func testAccAWSLBTargetGroupConfig_GRPC_ProtocolVersion(targetGroupName string) string {
return fmt.Sprintf(`
resource "aws_lb_target_group" "test" {
name = "%s"
port = 80
protocol = "HTTP"
protocol_version = "GRPC"
vpc_id = aws_vpc.test2.id

deregistration_delay = 200

stickiness {
type = "lb_cookie"
cookie_duration = 10000
}

health_check {
path = "/Test.Check/healthcheck"
interval = 60
port = 8080
protocol = "HTTP"
timeout = 3
healthy_threshold = 3
unhealthy_threshold = 3
matcher = "0-99"
}

tags = {
Name = "TestAccAWSLBTargetGroup_basic"
}
}

resource "aws_vpc" "test2" {
cidr_block = "10.10.0.0/16"

tags = {
Name = "terraform-testacc-lb-target-group-basic-2"
}
}

resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"

tags = {
Name = "terraform-testacc-lb-target-group-basic"
}
}
`, targetGroupName)
}

func testAccAWSLBTargetGroupConfig_updatedVpc(targetGroupName string) string {
return fmt.Sprintf(`
resource "aws_lb_target_group" "test" {
Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/lb_target_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,11 @@ The underlying function is invoked when `target_type` is set to `lambda`.
* `path` - (Required for HTTP/HTTPS ALB and HTTP NLB) The destination for the health check request. Applies to only HTTP/HTTPS.
* `port` - (Optional) The port to use to connect with the target. Valid values are either ports 1-65535, or `traffic-port`. Defaults to `traffic-port`.
* `protocol` - (Optional) The protocol to use to connect with the target. Defaults to `HTTP`. Not applicable when `target_type` is `lambda`.
* `protocol_version` - (Optional) The protocol version. Defaults to `HTTP1`. Specify GRPC to send requests to targets using GRPC, HTTP2 to send requests to targets using HTTP/2, HTTP1 to send requests to targets using HTTP/1.1.
* `timeout` - (Optional) The amount of time, in seconds, during which no response means a failed health check. For Application Load Balancers, the range is 2 to 120 seconds, and the default is 5 seconds for the `instance` target type and 30 seconds for the `lambda` target type. For Network Load Balancers, you cannot set a custom value, and the default is 10 seconds for TCP and HTTPS health checks and 6 seconds for HTTP health checks.
* `healthy_threshold` - (Optional) The number of consecutive health checks successes required before considering an unhealthy target healthy. Defaults to 3.
* `unhealthy_threshold` - (Optional) The number of consecutive health check failures required before considering the target unhealthy . For Network Load Balancers, this value must be the same as the `healthy_threshold`. Defaults to 3.
* `matcher` (Required for HTTP/HTTPS ALB) The HTTP codes to use when checking for a successful response from a target. You can specify multiple values (for example, "200,202") or a range of values (for example, "200-299"). Applies to Application Load Balancers only (HTTP/HTTPS), not Network Load Balancers (TCP).
* `matcher` (Required for HTTP/HTTPS/GRPC ALB) The response codes to use when checking for a healthy responses from a target. You can specify multiple values (for example, "200,202" for HTTP(s) or "0,12" for GRPC) or a range of values (for example, "200-299" or "0-99"). Applies to Application Load Balancers only (HTTP/HTTPS/GRPC), not Network Load Balancers (TCP).

## Attributes Reference

Expand Down