如何合并Terraform Map中的对象列表,聚合指定键的值?
Terraform 合并对象列表:保留标量键,合并值为集合/列表/字符串
我需要合并local.what_i_have_v2中的对象列表,将instance_id、tag_name这类值完全相同的键保留为标量,将tag_value这类键的值合并为集合、列表或拼接成字符串。
现有数据
locals { what_i_have_v2 = { "cluster=foo|instance=foo#1|tag=tag1" = [ { instance_id = "i-fff11111" tag_name = "tag1" tag_value = "val1_a" }, { instance_id = "i-fff11111" tag_name = "tag1" tag_value = "val1_b" }, ], "cluster=foo|instance=foo#2|tag=tag1" = [ { instance_id = "i-fff22222" tag_name = "tag1" tag_value = "val1_a" }, { instance_id = "i-fff22222" tag_name = "tag1" tag_value = "val1_b" }, ], "cluster=bar|instance=bar#1|tag=tag1" = [ { instance_id = "i-bbb11111" tag_name = "tag1" tag_value = "val1_a" }, ], "cluster=bar|instance=bar#1|tag=tag2" = [ { instance_id = "i-bbb11111" tag_name = "tag2" tag_value = "val2_a" }, { instance_id = "i-bbb11111" tag_name = "tag2" tag_value = "val2_b" }, ], }, }
期望输出
格式1:映射结构(保留实例级键)
locals { what_i_want_v1 = { "cluster=foo|instance=foo#1" = { instance_id = "i-fff11111" tag_name = "tag1" tag_value = ["val1_a", "val1_b"] # 相同键下的值合并为列表 }, "cluster=foo|instance=foo#2" = { instance_id = "i-fff22222" tag_name = "tag1" tag_value = ["val1_a", "val1_b"] }, "cluster=bar|instance=bar#1" = { instance_id = "i-bbb11111" tag_name = "tag1" tag_value = ["val1_a"] }, "cluster=bar|instance=bar#1" = { instance_id = "i-bbb11111" tag_name = "tag2" tag_value = ["val2_a", "val2_b"] }, }, }
格式2:列表结构
locals { what_i_want_v2 = [ { instance_id = "i-fff11111" tag_name = "tag1" tag_value = ["val1_a", "val1_b"] }, { instance_id = "i-fff22222" tag_name = "tag1" tag_value = ["val1_a", "val1_b"] }, { instance_id = "i-bbb11111" tag_name = "tag1" tag_value = ["val1_a"] }, { instance_id = "i-bbb11111" tag_name = "tag2" tag_value = ["val2_a", "val2_b"] }, ], }
格式3:列表结构(值拼接为字符串)
locals { what_i_want_v3 = [ { instance_id = "i-fff11111" tag_name = "tag1" tag_value = "val1_a+val1_b" # 值用"+"拼接为字符串 }, { instance_id = "i-fff22222" tag_name = "tag1" tag_value = "val1_a+val1_b" }, { instance_id = "i-bbb11111" tag_name = "tag1" tag_value = "val1_a" }, { instance_id = "i-bbb11111" tag_name = "tag2" tag_value = "val2_a+val2_b" }, ], }
尝试过的方法(无效)
使用merge()函数会直接覆盖重复键的值,无法实现合并:
locals { attempt_1 = {for k, v in local.what_i_have: k => merge(v...)} }
结果:
# attempt_1 = { "cluster=bar|instance=bar#1" = { instance_id = "i-bbb11111" tag_name = "tag1" tag_value = "val1_a" } "cluster=foo|instance=foo#1" = { instance_id = "i-fff11111" tag_name = "tag1" tag_value = "val1_b" } "cluster=foo|instance=foo#2" = { instance_id = "i-fff22222" tag_name = "tag1" tag_value = "val1_b" } }
可行解决方案
实现what_i_want_v1(映射结构)
利用正则表达式提取实例级键,结合for表达式收集tag_value:
locals { what_i_want_v1 = { for k, objs in local.what_i_have_v2 : // 从原始键中移除|tag=xxx部分,得到实例级标识 regex_replace(k, "\\|tag=.+$", "") => { instance_id = objs[0].instance_id // 列表内instance_id一致,取第一个即可 tag_name = objs[0].tag_name // 列表内tag_name一致,取第一个即可 tag_value = [for o in objs : o.tag_value] // 收集所有tag_value到列表 } } }
实现what_i_want_v2(列表结构)
直接提取what_i_want_v1的所有值转成列表:
locals { what_i_want_v2 = values(local.what_i_want_v1) }
实现what_i_want_v3(值拼接为字符串)
基于what_i_want_v2,用join()函数将列表值拼接为字符串:
locals { what_i_want_v3 = [ for item in local.what_i_want_v2 : merge(item, { tag_value = join("+", item.tag_value) }) ] }
补充说明
由于what_i_have_v2中每个键对应的对象列表里,instance_id和tag_name的值完全一致,因此可以安全地取列表第一个元素的对应值作为标量。如果后续存在值不一致的情况,可以先通过distinct()函数验证,避免出现数据不一致问题。
内容的提问来源于stack exchange,提问作者CDuv
相关产品推荐
相关产品推荐

