You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:47:34