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

Terraform遍历含空映射的自定义列表 求高效解决方案

Terraform 处理空映射过滤的高效方案

问题背景

我创建了自定义locals变量,通过嵌套for循环和if语句过滤值,但最终生成的local.data里混有空对象,在资源中遍历时触发错误。

自定义locals变量代码

locals {
 data = flatten([for value1 in object1 : [
          for value2 in value1.object2 : [ 
            for value3 in value2.object3 : 
 startwith(value3.id, "1") ? { 
      data1 = ...
      data2 = ...
      data3 = ...
    } : {}
  ]])
 ]
}

生成的local.data示例:

[
  {
    data1 = "a"
    data2 = "a"
    data3 = "a"
  },
  {},
  {},
  {
    data1 = "b"
    data2 = "b"
    data3 = "b"
  }
]

尝试的方案及错误

尝试1:直接遍历tuple

resource "DATA" "my_resource" {
  for_each = local.data
  
  name = each.value.data1
  value = each.value.data2
  description = each.value.data3
...
}

错误提示:

local.data is tuple with 4 element

尝试2:转为map后遍历

resource "DATA" "my_resource" {
  for_each = { for key, value in local.data : key => value
  
  name = each.value.data1
  value = each.value.data2
  description = each.value.data3
...
}

错误提示:

This map does not have an element with the key "data1"
This map does not have an element with the key "data2"
This map does not have an element with the key "data3"

补充需求

我已经有一个通过检查data1键是否存在来过滤的方案,但想找更高效的实现:

# 检查键存在与否判断是否为空对象
for_each = { for k, v in local.data : v => v if contains(keys(v), "data1")}

高效解决方案

方案1:在locals阶段直接过滤空对象

最省心的方式是在生成local.data时就剔除无效的空对象,避免后续重复处理:

locals {
 data = flatten([
  for value1 in object1 : [
    for value2 in value1.object2 : [ 
      for value3 in value2.object3 : 
        # 符合条件则生成对象,不符合返回null而非空对象
        startwith(value3.id, "1") ? { 
          data1 = ...
          data2 = ...
          data3 = ...
        } : null
    ]
  ]
])
# 过滤掉所有null值,得到纯有效对象列表
 data = [for item in local.data : item if item != null]
}

处理后local.data里全是有效对象,后续遍历资源时直接转成带唯一键的map即可(for_each要求键唯一且稳定):

resource "DATA" "my_resource" {
  # 用data1作为唯一键(确保data1值唯一),也可组合多个字段生成唯一键
  for_each = { for item in local.data : item.data1 => item }
  
  name = each.value.data1
  value = each.value.data2
  description = each.value.data3
}

方案2:简化for_each过滤逻辑

如果不想修改locals,直接在for_each里判断对象是否非空,比检查特定键更高效:

resource "DATA" "my_resource" {
  # 通过判断对象长度是否大于0,快速过滤空对象
  for_each = { for k, v in local.data : v.data1 => v if length(v) > 0 }
  
  name = each.value.data1
  value = each.value.data2
  description = each.value.data3
}

方案3:用compact函数一键过滤null

如果在locals里返回的是null而非空对象,可直接用compact函数移除所有null元素,一步到位:

locals {
 data = compact(flatten([
  for value1 in object1 : [
    for value2 in value1.object2 : [ 
      for value3 in value2.object3 : 
        startwith(value3.id, "1") ? { 
          data1 = ...
          data2 = ...
          data3 = ...
        } : null
    ]
  ]
]))
}

内容的提问来源于stack exchange,提问作者N. J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:25:23