Terraform如何合并含重复键的映射列表且不覆盖值
深度合并嵌套映射列表(重复键追加值而非覆盖)
问题说明
我有一个包含重复键的嵌套映射列表,需要将其合并为单个映射。对于重复的键,要求追加合并其对应的嵌套值,而不是用最新的映射值覆盖旧值。
输入示例
input_maps = [ { "e-p": { "a-emea": { "n@abc.com": { "role": "READER" } }, "c-emea": { "n@abc.com": { "role": "READER" } } }, "g-p": { "a-global": { "n@abc.com": { "role": "READER" } } } }, {}, { "g-p": { "a-global": { "r@abc.com": { "role": "READER" } }, "d-global": { "r@abc.com": { "role": "READER" } } }, "u-p": { "a-us": { "r@abc.com": { "role": "READER" } } } }, ]
期望输出
output_maps = { "e-p": { "a-emea": { "n@abc.com": { "role": "READER" } }, "c-emea": { "n@abc.com": { "role": "READER" } } }, "g-p": { "a-global": { "n@abc.com": { "role": "READER" }, "r@abc.com": { "role": "READER" } }, "d-global": { "r@abc.com": { "role": "READER" } } }, "u-p": { "a-us": { "r@abc.com": { "role": "READER" } } } }
尝试过的代码(存在覆盖问题)
output_maps = merge([ for input_map in local.input_maps:{ for key, value in input_map => { for sub_key, sub_value in value : sub_key => sub_value } } ]...)
这段代码用Terraform内置的merge函数做浅合并,遇到重复键(如g-p)时,会直接用后面的映射值覆盖前面的,无法实现嵌套层级的深度合并。
解决方案:递归深度合并
通过定义递归的合并函数,实现嵌套映射的深度合并,具体代码如下:
locals { # 递归合并两个嵌套映射:遇到相同键时继续合并子映射,而非覆盖 deep_merge = func(a, b) { # 若输入不是映射类型,直接返回b(适配非嵌套场景) if type(a) != object({}) || type(b) != object({}) { return b } # 合并所有键,共同键递归处理子映射 return merge( a, b, { for k in setintersection(keys(a), keys(b)) : k => local.deep_merge(a[k], b[k]) } ) } # 遍历列表中的所有映射,依次执行深度合并 output_maps = foldl(local.input_maps, {}, acc, m) => local.deep_merge(acc, m) }
代码说明
deep_merge函数:递归处理两个映射,当遇到相同键时,会继续合并它们的子映射,确保嵌套层级的内容被追加而非覆盖。foldl函数:将列表中的所有映射逐个传入deep_merge,从空映射开始累积合并结果,最终得到完整的合并后映射。
这个方法可以完美实现需求中的嵌套映射合并,比如g-p下的a-global会合并两个邮箱的角色条目,而不是替换原有内容。
内容的提问来源于stack exchange,提问作者neha sharma
相关产品推荐
相关产品推荐

