在 terraform 中合并列表内的地图

leo*_*ion 6 for-loop terraform

我有一个这样的地图列表 -

[
  {
    "outer_key_1" = [
      {
        "ip_cidr" = "172.16.6.0/24"
        "range_name" = "range1"
      },
      {
        "ip_cidr" = "172.16.7.0/24"
        "range_name" = "range2"
      },
      {
        "ip_cidr" = "172.17.6.0/24"
        "range_name" = "range3"
      },
      {
        "ip_cidr" = "172.17.7.0/24"
        "range_name" = "range4"
      },
    ]
  },
  {
    "outer_key_2" = [
      {
        "ip_cidr" = "172.16.5.0/24"
        "range_name" = "range5"
      },
      {
        "ip_cidr" = "172.17.5.0/24"
        "range_name" = "range6"
      },
    ]
  },
]
Run Code Online (Sandbox Code Playgroud)

我想合并列表中的地图。这是在一个输出变量中module.module_name.module_op

所需输出:


{
    "outer_key_1" = [
      {
        "ip_cidr" = "172.16.6.0/24"
        "range_name" = "range1"
      },
      {
        "ip_cidr" = "172.16.7.0/24"
        "range_name" = "range2"
      },
      {
        "ip_cidr" = "172.17.6.0/24"
        "range_name" = "range3"
      },
      {
        "ip_cidr" = "172.17.7.0/24"
        "range_name" = "range4"
      },
    ]

    "outer_key_2" = [
      {
        "ip_cidr" = "172.16.5.0/24"
        "range_name" = "range5"
      },
      {
        "ip_cidr" = "172.17.5.0/24"
        "range_name" = "range6"
      },
    ]
}
Run Code Online (Sandbox Code Playgroud)

我已经使用

locals {
  result = merge(module.module_name.module_op[0], module.module_name.module_op[1])
}
Run Code Online (Sandbox Code Playgroud)

我如何以更迭代的方式做到这一点。

我的列表中不会总是只有 2 张地图,它可以更多。

我尝试在 terraform 12 中像这样使用 for 循环 -

output "result" {
  value = [ for tuple in module.module_name.module_op : merge(tuple) ]
}
Run Code Online (Sandbox Code Playgroud)

和这个 -

output "secondary_subnets" {
  value = { for tuple in module.module_name.module_op : merge(tuple) }
}
Run Code Online (Sandbox Code Playgroud)

第一个给了我我的输入,第二个给了我一个错误,说我需要添加一个键,因为我正在返回一个对象。

有没有办法做到这一点?

提前致谢。

小智 23

您实际上可以将地图列表传递给merge()函数:

通过...在最后一个参数表达式后使用特殊符号,Terraform 语言具有将列表/元组转换为多个参数的通用功能

因此,在上面的示例中,您可以执行以下操作:

locals {
  result = merge(module.module_name.module_op...)
}
Run Code Online (Sandbox Code Playgroud)

这将合并列表中的所有地图,允许动态调整大小的列表。


小智 7

不幸的是,values()您的地图是列表。否则,您可以执行以下操作list(map(<not_list>))

例如

locals {
  my_list_of_maps = [
    {
       key1 = "val1"
       key2 = "val2"
    },
    {
       key3 = "val3"
    },
  ]
}

zipmap(
  flatten(
    [for item in local.my_list_of_maps : keys(item)]
  ),
  flatten(
    [for item in local.my_list_of_maps : values(item)]
  )
)
Run Code Online (Sandbox Code Playgroud)

这将像这样处理

zipmap(
  flatten([["key1", "key2"], ["key3"]]),
  flatten([["val1", "val2"], ["val3"]])
)
Run Code Online (Sandbox Code Playgroud)

=>

zipmap(
  ["key1", "key2", "key3"],
  ["val1", "val2", "val3"]
)
Run Code Online (Sandbox Code Playgroud)

=>

{
  key1 = "val1"
  key2 = "val2"
  key3 = "val3"
}
Run Code Online (Sandbox Code Playgroud)

我在list(map(string))这里使用了一个简单的,但values()地图的可能更复杂。但是,由于flatten()使用了(递归地展平嵌套列表),values()所以不能是列表本身。

为了让它发挥作用,您可以随时将数据转换为如下所示:

[
  {
    "outer_key_1" = {
      range1 = "172.16.6.0/24"
      range2 = "172.16.7.0/24"
      range3 = "172.17.6.0/24"
      range4 = "172.17.7.0/24"
    }
  },
  {
    "outer_key_2" = {
      range5 = "172.16.5.0/24"
      range6 = "172.17.5.0/24"
    }
  },
]
Run Code Online (Sandbox Code Playgroud)

上面的逻辑可以毫无问题地解决这个问题。

顺便说一句,zipmap()表现得像一个merge(). 所以如果有重复的钥匙,迟到的钥匙会覆盖现有的钥匙。