I know - there was a topic with an explanation of how to solve this with flatten function. Help me understand how it works, please.
So, I'm setting up terraform with the vSphere provider. I want to achieve a goal when the network data source is configured dynamically from virtual machine's settings.
I have the variable "virtual_machines" in vars.tf with VM setting:
variable "virtual_machines" {
type = map(object({
template = string
host_name = string
domain_name = string
num_cpus = number
memory = number
dns_server_list = list(string)
gateway = string
interfaces = list(object({
network = string
ipv4_address = string
ipv4_netmask = string
}))
}))
}
And there are its values in vm.auto.rfvars:
virtual_machines = {
"gw" = {
template = "cent7_template"
host_name = "gw"
domain_name = "contoso.com"
dns_server_list = ["8.8.8.8", "8.8.4.4"]
num_cpus = 2
memory = 2048
interfaces = [
{
ipv4_address = "192.168.5.240"
ipv4_netmask = "24"
network = "VM Network"
},
{
ipv4_address = "192.168.4.241"
ipv4_netmask = "24"
network = "VM Network2"
}
]
gateway = "192.168.5.251"
}
}
In my main file there are sphere interfaces:
data "vsphere_network" "interfaces" {
for_each = networks.local
name = each.value.network
datacenter_id = data.vsphere_datacenter.dc.id
}
I have big trouble understanding how to make this local var to get "network" value from "interfaces" object list.
There is my try:
locals {
networks = flatten([
for vm_key, objects in var.virtual_machines : [
for interface in objects.interfaces : {
network = interface.network
ipv4_address = interface.ipv4_address
ipv4_netmask = interface.ipv4_netmask
}
])
}
After running this code I got the error:
│ local.networks is tuple with 2 elements
│
│ The given "for_each" argument value is unsuitable: the "for_each" argument must be a map, or set of
│ strings, and you have provided a value of type tuple.
Help please understand how to iterate to this value please. Big thanx!
Your local.networks
is a list of maps. You can't use such a data structure with for_each
. But you can use a map of maps. The easiest way to convert it to a map of maps is:
data "vsphere_network" "interfaces" {
for_each = {for idx, val in local.networks: idx => val}
name = each.value.network
datacenter_id = data.vsphere_datacenter.dc.id
}