Terraform:使用for_each和条件遍历本地映射列表的两类问题
Terraform for_each 映射列表遍历问题解决
首先是你定义的本地映射列表:
locals { networking = [ { name = "first" domain = "first.${local.dns_name}" port = 8080 group = "eighties" }, { name = "second" domain = "second.${local.dns_name}" port = 8081 group = "eighties" }, { name = "third" domain = "third.${local.dns_name}" port = 9090 group = "nineties" }, { name = "fourth" port = 9091 group = "nineties" } ] }
对应的DNS资源配置:
resource "google_dns_record_set" "dns_records" { for_each = { for k in local.networking: k.domain => k if k.domain != null } name = each.value.domain type = "A" ttl = 300 managed_zone = var.managed_zone project = var.dns_project rrdatas = [google_compute_global_address.default-forwarding-address.address] }
针对你遇到的两个问题,直接给出解决方案:
问题1:跳过无domain键的项,避免报错
直接访问k.domain会因为部分项没有该键触发错误,需要先检查键是否存在,再判断值是否非空。修改for_each的条件:
for_each = { for k in local.networking: k.domain => k if contains(keys(k), "domain") && k.domain != null }
或者用lookup函数给不存在的键返回默认值null,再判断:
for_each = { for k in local.networking: k.domain => k if lookup(k, "domain", null) != null }
两种方式都能跳过没有domain键的项,正常执行。
问题2:筛选特定分组时避免重复键报错
for_each要求键必须唯一,用k.group当键会因为同组项重复触发错误。解决思路是生成唯一键,比如结合name和group,或者直接用唯一的name作为键,同时保留分组筛选条件:
方案1:用name+group作为唯一键
for_each = { for k in local.networking: "${k.name}-${k.group}" => k if k.group == "eighties" }
方案2:直接用唯一的name作为键
for_each = { for k in local.networking: k.name => k if k.group == "eighties" }
如果确实需要按分组聚合数据,可以用...语法(如k.group => k...),但这种方式会把同组项打包成列表,无法直接用于资源的for_each(因为资源需要每个实例对应单个项),所以上面的两种方案更适合资源创建场景。
无需放弃映射列表的方案,通过调整for_each的键生成和条件判断逻辑就能解决问题。
内容的提问来源于stack exchange,提问作者Kapawn
相关产品推荐
相关产品推荐

