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

Terraform遍历嵌套列表时遭遇null值迭代错误,求排查

Terraform迭代null值问题排查

输入变量

appr = {
  "product1" = {WO = ["6470"], RO = ["6471","5538"]},
  "product2" = {RO = ["6472"]}
}

错误信息

│ Error: Iteration over null value
│
│   on ../../modules/sa_pc/main.tf line 15, in locals:
│   14:       for co, coo in clsan : [
│   15:         for applo in coo : [
│   16:           for op in ( co == "RO" ? ["READ","DESCRIBE"] : ["WRITE"] ) :  {
│   17:              oper = op
│   18:              
│   19:              appid_lo = applo
│   20:              opic-name = opi
│   21:              process = co
│   22:             }
│   23:         ]
│   24:       ]
│
│ A null value cannot be used as the collection in a 'for' expression.

问题描述

执行terraform plan时提示coo为null值无法迭代,但在terraform console中能得到预期输出。coo是通过for循环遍历的列表。

已尝试的代码

locals {
  acl_out = flatten([
    for opi, clsan in var.appr : [
      for co, coo in clsan : [
        for applo in coo : [
           for op in ( co == "RO" ? ["READ","DESCRIBE"] : ["WRITE"]) : {
             oper = op
             appid_lo = applo
             opic-name = opi
             process = co
           }
        ]
      ]
    ]
  ])
}

问题原因

核心差异在于Terraform的静态类型检查和动态运行计算的区别:

  • terraform plan会做静态类型推断,由于输入变量未显式约束类型,它会认为var.appr的结构允许某个操作类型(比如WO/RO)对应的值为null,因此提前检测到潜在的null迭代风险并报错。
  • terraform console基于当前输入的实际值动态计算,当前输入里没有null值,所以能正常输出结果。

解决方案

方案1:过滤null值

在遍历coo前先判断是否为null,仅处理非null的情况:

locals {
  acl_out = flatten([
    for opi, clsan in var.appr : [
      for co, coo in clsan : coo != null ? [
        for applo in coo : [
          for op in (co == "RO" ? ["READ", "DESCRIBE"] : ["WRITE"]) : {
            oper      = op
            appid_lo  = applo
            opic-name = opi
            process   = co
          }
        ]
      ] : []
    ]
  ])
}

方案2:默认空列表兜底

用try()函数给coo设置默认空列表,确保永远是可迭代的集合:

locals {
  acl_out = flatten([
    for opi, clsan in var.appr : [
      for co, coo in clsan : [
        for applo in try(coo, []) : [
          for op in (co == "RO" ? ["READ", "DESCRIBE"] : ["WRITE"]) : {
            oper      = op
            appid_lo  = applo
            opic-name = opi
            process   = co
          }
        ]
      ]
    ])
}

额外优化:显式约束变量类型

如果能确定var.appr的结构中,WO/RO的值永远是列表(不会为null),可以给变量添加显式类型约束,从根源避免类型推断的问题:

variable "appr" {
  type = map(object({
    WO = optional(list(string), [])
    RO = optional(list(string), [])
  }))
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:06:14