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

Terraform for_each资源结合dynamic块报错问题排查

Terraform配置aws_lb_listener_rule时host_header动态块报错根源分析

问题场景

使用Terraform的aws_lb_listener_rule资源,通过for_each遍历lb_rules变量创建规则时,添加dynamic host_header块后触发错误:"Can't access attributes on a primitive-typed value (string)",移除该动态块则可正常运行。

输入变量数据

lb_rules = tolist([
  {
    "host" = "dest-1.example.uk"
    "name" = "redirect-host"
    "path" = "/"
    "path_pattern" = tolist([
      "",
    ])
    "host_header" = tolist([
      "origin-1.example.uk",
    ])
    "port" = "#{port}"
    "priority" = 5
    "protocol" = "#{protocol}"
    "status_code" = "HTTP_301"
    "type" = "dev"
  },
  {
    "host" = "dest-2.example.uk"
    "name" = "redirect-all"
    "path" = "/"
    "path_pattern" = tolist([
      "/*",
    ])
    "host_header" = tolist([
      "origin-2.example.uk",
    ])
    "port" = "#{port}"
    "priority" = 100
    "protocol" = "#{protocol}"
    "status_code" = "HTTP_301"
    "type" = "stage"
  }
])

资源配置代码

resource "aws_lb_listener_rule" "redirect" {

  for_each = { for r in var.lb_rules : r.name => r }

  listener_arn = aws_lb_listener.default.arn
  priority     = each.value.priority

  action {
    type = "redirect"
    redirect {
      protocol    = each.value.protocol
      host        = each.value.host
      port        = each.value.port
      path        = each.value.path
      status_code = each.value.status_code
    }
  }

  condition {
    dynamic "host_header" {
      for_each = each.value.host_header 
      content {
        values = host_header.value.*.host_header
      }
    }
  }

  tags = {
    Name = each.value.name
  }

}

错误根源

问题出在dynamic host_header块的values赋值逻辑:

  • each.value.host_header是字符串组成的列表(比如["origin-1.example.uk"]),当dynamic循环遍历这个列表时,host_header.value对应的是单个字符串(原始primitive类型)。
  • 代码中host_header.value.*.host_header试图访问该字符串的host_header属性,但字符串属于原始类型,不存在任何属性,直接触发Terraform的类型校验错误。

修正方案

aws_lb_listener_rule的condition块中,host_header的values参数需要接收字符串列表。由于循环时每个host_header.value已经是单个字符串,只需将其包装为列表即可:

condition {
  dynamic "host_header" {
    for_each = each.value.host_header 
    content {
      values = [host_header.value]
    }
  }
}

如果host_header列表本身就是要作为values的完整值,还可以直接简化(无需dynamic循环):

condition {
  host_header {
    values = each.value.host_header
  }
}

内容的提问来源于stack exchange,提问作者Theo Sweeny

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:34:57