Unfortunately, it seems aws_lb_target_group cannot be modular supporting both TCP and HTTP(S) in the same module.
health_check {
path = "${local.healthcheck_path }"
port = "${local.healthcheck_port }"
matcher = "${local.healthcheck_match_codes }"
timeout = "${local.healthcheck_timeout }"
interval = "${var.healthcheck_interval }"
protocol = "${local.healthcheck_protocol }"
healthy_threshold = "${var.healthcheck_healthy_threshold }"
unhealthy_threshold = "${var.healthcheck_unhealthy_threshold}"
}
If timeout is present and the target group type is TCP the following error always occurs:
* module.client_nlb_target.aws_lb_target_group.scope: : custom timeout is not supported for target_groups with TCP protocol
I have tried using locals to set the value of local.healthcheck_timeout to the following to make the code modular:
ValidateFunc: validation.IntBetween(2, 60),)TCP healthcheck, it still says that a custom timeout is not supported. if t := healthCheck["timeout"].(int); t != 0 && diff.Id() == "" {
// timeout has a default value, so only check this if this is a network
// LB and is a first run
return fmt.Errorf("%s: custom timeout is not supported for target_groups with TCP protocol", diff.Id())
}
It looks like to make Terraform ignore the value, it should be 0 or blank, both of which fail validation.
Thanks !
Hi @rlees85 ๐ Sorry you're having trouble here. There are some interesting limitations in working with ELBv2 APIs and the health check information certainly has caused issues in the past.
This issue should be resolvable without changes to the AWS provider once Terraform 0.12 has released as it will include support for passing null to attributes, which will avoid triggering the attribute validation. I believe for now (without code changes to the resource) you will need to create two separate aws_lb_target_group configurations and use count to determine which to enable.
Fair enough, thanks for the reply. I'm glad that I'm not missing something obvious.
I just thought I'd raise it in case the validation (2-60) is no longer relevant now the module also supports NLB (or it should be checking against 10 as nil for the NLB timeout value check).
Look forward to 0.12, I think a lot of my modules will be able to be consolidated!
Hi @rlees85 ๐ This issue is resolved in Terraform 0.12, which supports new functionality in the configuration language aimed at solving problems like these. The new dynamic block syntax can be used to dynamically generate configuration blocks and their arguments. These can be combined with the new null value, which can be used to omit arguments as if they were not defined in the configuration at all.
For example, given this configuration:
# main.tf
terraform {
required_providers {
aws = "2.20.0"
}
required_version = "0.12.5"
}
provider "aws" {
region = "us-east-1"
}
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
}
module "test1" {
source = "./module1"
health_check = []
vpc_id = aws_vpc.test.id
}
module "test2" {
source = "./module1"
health_check = [{
healthy_threshold = null
interval = null
matcher = "200-299"
path = "/"
port = null
protocol = "HTTP"
timeout = null
unhealthy_threshold = null
}]
vpc_id = aws_vpc.test.id
}
# module1/main.tf
variable "health_check" {
type = list(object({
healthy_threshold = number
interval = number
matcher = string
path = string
port = number
protocol = string
timeout = number
unhealthy_threshold = number
}))
}
variable "vpc_id" {
type = string
}
resource "aws_lb_target_group" "test" {
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
dynamic "health_check" {
for_each = var.health_check
content {
healthy_threshold = health_check.value.healthy_threshold
interval = health_check.value.interval
matcher = health_check.value.matcher
path = health_check.value.path
port = health_check.value.port
protocol = health_check.value.protocol
timeout = health_check.value.timeout
unhealthy_threshold = health_check.value.unhealthy_threshold
}
}
}
Produces the following apply output:
$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_vpc.test will be created
+ resource "aws_vpc" "test" {
+ arn = (known after apply)
+ assign_generated_ipv6_cidr_block = false
+ cidr_block = "10.0.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_classiclink = (known after apply)
+ enable_classiclink_dns_support = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = true
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
}
# module.test1.aws_lb_target_group.test will be created
+ resource "aws_lb_target_group" "test" {
+ arn = (known after apply)
+ arn_suffix = (known after apply)
+ deregistration_delay = 300
+ id = (known after apply)
+ lambda_multi_value_headers_enabled = false
+ name = (known after apply)
+ port = 80
+ protocol = "HTTP"
+ proxy_protocol_v2 = false
+ slow_start = 0
+ target_type = "instance"
+ vpc_id = (known after apply)
+ health_check {
+ enabled = (known after apply)
+ healthy_threshold = (known after apply)
+ interval = (known after apply)
+ matcher = (known after apply)
+ path = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
+ timeout = (known after apply)
+ unhealthy_threshold = (known after apply)
}
+ stickiness {
+ cookie_duration = (known after apply)
+ enabled = (known after apply)
+ type = (known after apply)
}
}
# module.test2.aws_lb_target_group.test will be created
+ resource "aws_lb_target_group" "test" {
+ arn = (known after apply)
+ arn_suffix = (known after apply)
+ deregistration_delay = 300
+ id = (known after apply)
+ lambda_multi_value_headers_enabled = false
+ name = (known after apply)
+ port = 80
+ protocol = "HTTP"
+ proxy_protocol_v2 = false
+ slow_start = 0
+ target_type = "instance"
+ vpc_id = (known after apply)
+ health_check {
+ enabled = true
+ healthy_threshold = 3
+ interval = 30
+ matcher = "200-299"
+ path = "/"
+ port = "traffic-port"
+ protocol = "HTTP"
+ timeout = (known after apply)
+ unhealthy_threshold = 3
}
+ stickiness {
+ cookie_duration = (known after apply)
+ enabled = (known after apply)
+ type = (known after apply)
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_vpc.test: Creating...
aws_vpc.test: Creation complete after 2s [id=vpc-047ef4cec5efc2955]
module.test1.aws_lb_target_group.test: Creating...
module.test2.aws_lb_target_group.test: Creating...
module.test1.aws_lb_target_group.test: Creation complete after 0s [id=arn:aws:elasticloadbalancing:us-east-1:--OMITTED--:targetgroup/tf-20190724074317849500000001/ac44b2a3a2c3d4fe]
module.test2.aws_lb_target_group.test: Creation complete after 0s [id=arn:aws:elasticloadbalancing:us-east-1:--OMITTED--:targetgroup/tf-20190724074317850400000002/a264755154d3b092]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Enjoy! ๐
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!
Most helpful comment
Hi @rlees85 ๐ This issue is resolved in Terraform 0.12, which supports new functionality in the configuration language aimed at solving problems like these. The new
dynamicblock syntax can be used to dynamically generate configuration blocks and their arguments. These can be combined with the newnullvalue, which can be used to omit arguments as if they were not defined in the configuration at all.For example, given this configuration:
Produces the following apply output:
Enjoy! ๐