使用for_each为多Listener创建aws_lb_listener_rule遇类型错误求助
问题:为多个Listener创建相同规则时的listener_arn类型错误
报错信息
│ Error: Incorrect attribute value type │ │ on modules/aws/alb/lb_listener_rule/03-main.tf line 4, in resource "aws_lb_listener_rule" "www_redirect": │ 4: listener_arn = each.value.listener_arn │ ├──────────────── │ │ each.value.listener_arn is tuple with 1 element │ │ Inappropriate value for attribute "listener_arn": string required.
现有配置代码
模块调用代码
module "lb_listener_rule_http" { source = "./modules/aws/alb/lb_listener_rule" listener_arn = module.alb_lb_listener.frontend_http tags = merge(local.tags, { Name = var.domain }) domain_name_public = var.domain listener_rules_http_redirect = { // redirect www to non www 1 = { listener_arn = [ { http = module.alb_lb_listener.frontend_http, https = module.alb_lb_listener.frontend_https } ], action = [ { "type" = "redirect", "target_group_arn" = module.target_group.arns[local.target_group_name_wp], } ], redirect = [ { host = var.domain path = "/#{path}" query = "#{query}" port = "443" protocol = "HTTPS" status_code = "HTTP_301" } ] conditions = [ { "field" = "host-header" "values" = ["www.${var.domain}"] } ] }, } }
模块资源代码
resource "aws_lb_listener_rule" "www_redirect" { for_each = var.listener_rules_http_redirect listener_arn = each.value.listener_arn priority = each.key dynamic "action" { for_each = each.value["action"] content { type = action.value.type dynamic "redirect" { for_each = each.value["redirect"] content { host = redirect.value.host path = redirect.value.path query = redirect.value.query port = redirect.value.port protocol = redirect.value.protocol status_code = redirect.value.status_code } } } } dynamic "condition" { for_each = each.value["conditions"] content { dynamic "host_header" { for_each = condition.value.field == "host-header" ? [condition.value.field] : [] content { values = condition.value.values } } dynamic "path_pattern" { for_each = condition.value.field == "path-pattern" ? [condition.value.field] : [] content { values = condition.value.values } } dynamic "source_ip" { for_each = condition.value.field == "source-ip" ? [condition.value.field] : [] content { values = condition.value.values } } } } }
变量定义
variable "listener_rules_http_redirect" { type = map(any) default = {} }
解决思路
1. 修正listener_arn的结构
当前listener_arn是嵌套对象的数组,不符合aws_lb_listener_rule对单个字符串类型的要求。将其调整为直接存储Listener ARN的字符串数组:
listener_rules_http_redirect = { 1 = { listener_arn = [ module.alb_lb_listener.frontend_http, module.alb_lb_listener.frontend_https ], // action、redirect、conditions配置保持不变 } }
2. 重构模块的for_each逻辑
通过局部值展开规则与Listener的组合,为每个Listener生成独立的规则实例:
locals { expanded_rules = merge([ for rule_key, rule in var.listener_rules_http_redirect : { for idx, listener_arn in rule.listener_arn : "${rule_key}-${idx}" => { listener_arn = listener_arn action = rule.action redirect = rule.redirect conditions = rule.conditions priority = rule_key } } ]...) } resource "aws_lb_listener_rule" "www_redirect" { for_each = local.expanded_rules listener_arn = each.value.listener_arn priority = each.value.priority // 后续dynamic action、condition代码保持不变 }
3. 强类型变量定义(可选)
将变量类型从map(any)改为明确的结构,提前规避结构错误:
variable "listener_rules_http_redirect" { type = map(object({ listener_arn = list(string) action = list(object({ type = string target_group_arn = optional(string) })) redirect = list(object({ host = string path = string query = string port = string protocol = string status_code = string })) conditions = list(object({ field = string values = list(string) })) })) default = {} }
内容的提问来源于stack exchange,提问作者Rostyslav Malenko
相关产品推荐
相关产品推荐

