Reputation: 23
I'm coming with a problem I cannot solve for a few days now. I have a data structure defining data disks, consisting of a list of maps per disk:
variable "data_disks_node" {
description = "Data disk configuration lun, size in gib, mountpoint"
default = [
{
lun = 0
size = 200
mount = "/opt/mount1"
},
{
lun = 1
size = 32
mount = "/opt/mount2"
},
]
}
I am using this structure to create data disks using a dynamic block and for_each (which is working great) but need to create a map of tags with values sourced from the same data structure.
I need to tag created resources with their configured data disks and mount points (don't ask, cant change that requirement) and need the following map result:
data_disk_tags = {
lun0 = "/opt/mount1"
lun1 = "/opt/mount2"
}
so not only do I need to create a map from the list of maps but also need to filter results, map one value as key and another value as value, and also need to prefix the new key with a string "lun". I'm at my wits end with this as I only worked here and there with Terraform and am unable to find any documented cases where this issue was solved. Terraform used is 0.12.20 if it matters. The closest (and it's not even close) that I came so far is this:
locals {
vm_joined_tags = merge(var.vm_tags, zipmap(flatten([for item in var.vm_data_disk_configuration : keys(item)]), flatten([for item in var.vm_data_disk_configuration : values(item)])))
}
which works but creates a map of only the first sourced map and key values like
{
lun = 1
size = 200
mount = "/opt/mount1"
}
with the second map not even present. I'm very grateful for any help or pointers towards a possible solution. Changing the data structure is possible but should be avoided if possible since other module code relies on it. Ff any further input is needed tell me and I will provide.
Upvotes: 2
Views: 4229
Reputation: 56987
You look like you were on the right path with trying to loop over the list but there's a simpler way to get that:
variable "data_disks_node" {
description = "Data disk configuration lun, size in gib, mountpoint"
default = [
{
lun = 0
size = 200
mount = "/opt/mount1"
},
{
lun = 1
size = 32
mount = "/opt/mount2"
},
]
}
locals {
vm_joined_tags = { for disk in var.data_disks_node : format("lun%s", disk.lun) => disk.mount }
}
output "vm_joined_tags" {
value = local.vm_joined_tags
}
Applying this outputs your desired structure:
Outputs:
vm_joined_tags = {
"lun0" = "/opt/mount1"
"lun1" = "/opt/mount2"
}
Putting braces around the for expression means that it creates a map (it shares a similar syntax to Python's dictionary comprehensions):
The type of brackets around the for expression decide what type of result it produces. The above example uses
[
and]
, which produces a tuple. If{
and}
are used instead, the result is an object, and two result expressions must be provided separated by the=>
symbol:{for s in var.list : s => upper(s)}
So then the above example loops over the disks in var.data_disks_node
and creates a map with a key with the lun
of each disk, prefixed with the string "lun"
and a value of the mount
of each disk.
Upvotes: 3