I have the following input as list of maps where there are duplicate keys. I want to merge these maps into a single map where for each duplicate keys, the values are appended instead of replaced by the latest values.
Input:
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:
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"
}
}
}
}
I have tried following code:
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
}
}
]...)
This code replaces the values instead of merging the values for a key (for-example key "g-p"). I have tried various ways however, could not make the deep merge work.
Working example:
locals {
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"
}
}
}
}
]
# Flatten the input maps into a list of maps
# Each map contains the map_key, zone_key, and roles
flatten_maps = flatten([
for _, input_map in local.input_maps : [
for map_key, zones in input_map : [
for zone_key, roles in zones : {
map_key = map_key,
zone_key = zone_key,
value = roles
}
]
]
])
# Merge the maps into a single map
# Key consists of the map_key and zone_key
# Value consists of roles grouped by zone_key and map_key
merged_maps = {
for map in local.flatten_maps :
"${map.map_key}|${map.zone_key}" => map.value...
}
# Output the merged maps
output_maps = merge([
for _, input_map in local.input_maps : {
for map_key, zones in input_map : map_key => {
for zone_key, roles in zones : zone_key =>
local.merged_maps["${map_key}|${zone_key}"]
}
}
]...)
}
output "flatten_maps" {
value = local.flatten_maps
}
output "merged_maps" {
value = local.merged_maps
}
output "output_maps" {
value = local.output_maps
}
Running terraform plan
:
Changes to Outputs:
+ flatten_maps = [
+ {
+ map_key = "e-p"
+ value = {
+ "n@abc.com" = {
+ role = "READER"
}
}
+ zone_key = "a-emea"
},
+ {
+ map_key = "e-p"
+ value = {
+ "n@abc.com" = {
+ role = "READER"
}
}
+ zone_key = "c-emea"
},
+ {
+ map_key = "g-p"
+ value = {
+ "n@abc.com" = {
+ role = "READER"
}
}
+ zone_key = "a-global"
},
+ {
+ map_key = "g-p"
+ value = {
+ "r@abc.com" = {
+ role = "READER"
}
}
+ zone_key = "a-global"
},
+ {
+ map_key = "g-p"
+ value = {
+ "r@abc.com" = {
+ role = "READER"
}
}
+ zone_key = "d-global"
},
+ {
+ map_key = "u-p"
+ value = {
+ "r@abc.com" = {
+ role = "READER"
}
}
+ zone_key = "a-us"
},
]
+ merged_maps = {
+ "e-p|a-emea" = [
+ {
+ "n@abc.com" = {
+ role = "READER"
}
},
]
+ "e-p|c-emea" = [
+ {
+ "n@abc.com" = {
+ role = "READER"
}
},
]
+ "g-p|a-global" = [
+ {
+ "n@abc.com" = {
+ role = "READER"
}
},
+ {
+ "r@abc.com" = {
+ role = "READER"
}
},
]
+ "g-p|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"
}
},
]
}
}