I have a list of maps like this -
[
{
"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"
},
]
},
]
I want to merge the maps inside the list. This is in an output variable module.module_name.module_op
.
Required Output:
{
"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"
},
]
}
I have done this using
locals {
result = merge(module.module_name.module_op[0], module.module_name.module_op[1])
}
How do I do this in a more iterative way.
I will not always only 2 maps in my list, it can be more.
I tried using the for loop in terraform 12 like this -
output "result" {
value = [ for tuple in module.module_name.module_op : merge(tuple) ]
}
and this -
output "secondary_subnets" {
value = { for tuple in module.module_name.module_op : merge(tuple) }
}
The first one gives me my input back and the second one gives me an error saying I need to add a key since I am returning an object.
Is there a way to get this done?
Thanks in advance.
You can use terraform merge() function to combine multiple maps into a single map. merge() takes an arbitrary number of maps or objects, and returns a single map or object that contains a merged set of elements from all arguments.
» concat Function concat takes two or more lists and combines them into a single list.
Maps are a collection of string keys and string values. These can be useful for selecting values based on predefined parameters such as the server configuration by the monthly price.
You can actually pass a list of maps to the merge()
function:
The Terraform language has a general feature for turning lists/tuples into multiple arguments, by using the special symbol
...
after the last argument expression
So, in your example above, you could do:
locals {
result = merge(module.module_name.module_op...)
}
This will then merge all of the maps in the list, allowing for dynamically sized lists.
Unfortunately, the values()
of your maps are lists. Otherwise you could do the following which will work for list(map(<not_list>))
:
e.g.
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)]
)
)
this will process like so
zipmap(
flatten([["key1", "key2"], ["key3"]]),
flatten([["val1", "val2"], ["val3"]])
)
=>
zipmap(
["key1", "key2", "key3"],
["val1", "val2", "val3"]
)
=>
{
key1 = "val1"
key2 = "val2"
key3 = "val3"
}
i have used a simple list(map(string))
here but the values()
of the map can be more complex. however, since flatten()
is used (which flattens nested lists recursively), the values()
cannot be lists themselves.
in order to get this to work, you could always transform your data to look like this instead:
[
{
"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"
}
},
]
the above logic will work for that without a problem.
by the way, zipmap()
behaves like a merge()
. so if there are duplicate keys, the late arrivals will overwrite the existing keys.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With