I'm trying to create loadbalancer target group attachments via a for_eah approach to safe myself a lot of coding time. However I can't seem to use a for_each in a for_each. Does anyone have a pointer on this?
Additional explanation:
The resource aws_lb_target_group_attachment only accepts a single target_id in the form of a string, pointing to an instance ID.
So in this case I would like the resource to be created twice. Once for each target_id in the list of target_ids.
locals {
dev_alb_defaults = {
vpc_id = local.dev_alb_vpc_id
health_check_enabled = true
health_check_interval = 30
health_check_timeout = 5
health_check_healthy_threshold = 2
health_check_unhealthy_threshold = 2
health_check_matcher = 200
}
dev_alb_targets = {
i-am-service = {
tg_port = 443
target_ids = [ "i-0123456789ab", "i-0123456789bc" ]
}
}
}
resource "aws_lb_target_group" "dev_lb_tg" {
for_each = { for k, v in local.dev_alb_targets : k => v }
name = "${var.customer}-${var.dev_prefix}-${try(each.value.name, each.key)}-tg"
port = try(each.value.tg_port, null)
protocol = try(each.value.tg_protocol, null)
vpc_id = try(each.value.vpc_id,local.dev_alb_defaults.vpc_id, null)
health_check {
enabled = try(each.value.health_check_enabled, local.dev_alb_defaults.health_check_enabled, false)
path = try(each.value.health_check_path, local.dev_alb_defaults.health_check_path, null)
port = try(each.value.health_check_port, each.value.tg_port, null)
protocol = try(each.value.health_check_protocol, local.dev_alb_defaults.health_check_protocol, null)
interval = try(each.value.health_check_interval, local.dev_alb_defaults.health_check_interval, null)
timeout = try(each.value.health_check_timeout, local.dev_alb_defaults.health_check_timeout, null)
healthy_threshold = try(each.value.health_check_healthy_threshold, local.dev_alb_defaults.health_check_healthy_threshold, null)
unhealthy_threshold = try(each.value.health_check_unhealthy_threshold, local.dev_alb_defaults.health_check_unhealthy_threshold, null)
matcher = try(each.value.health_check_matcher, local.dev_alb_defaults.health_check_matcher, null)
}
}
resource "aws_lb_target_group_attachment" "dev_lb_tg" {
for_each = { for k, v in local.dev_alb_targets : k => v }
target_group_arn = aws_lb_target_group.dev_lb_tg["${try(each.value.name, each.key)}"].arn
port = try(each.value.tg_port, null)
target_id = try(each.value.target_ids, null)
}
}
The effect I hoped it had is: creating only 1 target group and creating 2 aws_lb_target_group_attachments. It creates 1 target group, however it does not create 2 target group attachments. I've tried variants in which I used tolist() for tg_instances or tostring() However I can't get it to accept the input.
╷
│ Error: Incorrect attribute value type
│
│ on dev-alb.tf line 288, in resource "aws_lb_target_group_attachment" "dev_lb_tg":
│ 288: target_id = each.value.target_ids
│ ├────────────────
│ │ each.value.target_ids is list of string with 2 elements
│
│ Inappropriate value for attribute "target_id": string required.
╵
Intermediate solution I have right now, which I don't like to use and I would like to condense to a proper solution:
locals {
dev_alb_defaults = {
target_id1 = "i-0123456789ab"
target_id2 = "i-0123456789bc"
}
dev_alb_targets = {
i-am-service = {
tg_port = 443
}
}
}
resource "aws_lb_target_group_attachment" "dev_lb_tg1" {
for_each = { for k, v in local.dev_alb_targets : k => v }
target_group_arn = aws_lb_target_group.dev_lb_tg["${try(each.value.name, each.key)}"].arn
port = try(each.value.tg_port, null)
target_id = local.dev_alb_defaults.target_id1
}
}
resource "aws_lb_target_group_attachment" "dev_lb_tg2" {
for_each = { for k, v in local.dev_alb_targets : k => v }
target_group_arn = aws_lb_target_group.dev_lb_tg["${try(each.value.name, each.key)}"].arn
port = try(each.value.tg_port, null)
target_id = local.dev_alb_defaults.target_id2
}
}
You have to flatten you local variable:
locals {
dev_alb_targets = {
i-am-service = {
tg_port = 443
target_ids = [ "i-0123456789ab", "i-0123456789bc" ]
}
}
flat_dev_alb_targets = merge([
for service, details in local.dev_alb_targets: {
for target in details.target_ids:
"${service}-${target}" => {
tg_port = details.tg_port
target_id = target
}
}
]...) # no NOT remove the dots
}
then
resource "aws_lb_target_group_attachment" "dev_lb_tg" {
for_each = local.flat_dev_alb_targets
target_group_arn = aws_lb_target_group.dev_lb_tg["${try(each.value.name, each.key)}"].arn
port = try(each.value.tg_port, null)
target_id = try(each.value.target_id, null)
}
}
Also your code does not show what each.value.name
is, so its difficult to speculate on full aspects and requirements on how to flatten it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.