I need a help again.
I need to generate network interfaces dynamically. For this purpose i declare interfaces in the vm config like this:
`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 = "10.10.0.1"
ipv4_netmask = "24"
network = "Contoso Lan"
}
]
gateway = "192.168.5.251"
}
"lab" = {
template = "cent7_template"
host_name = "lab"
domain_name = "contoso.com"
dns_server_list = ["8.8.8.8", "8.8.4.4"]
num_cpus = 2
memory = 2048
interfaces = [
{
ipv4_address = "10.10.0.2"
ipv4_netmask = "24"
network = "Contoso Lan"
}
]
gateway = "10.10.0.1"
}
}`
To iterate through interfaces and generate it as data source i created local:
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
}
]
])
}
And dynamic data source:
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
}
But this resource code generates all of the interfaces that are declared in all vm's. For example, my first vm have 2 interfaces(VM Network and Contoso Lan), my second interface have 1 interface Contoso Lan and my code want to create 3 interfaces in summary but i need to create interfaces that are declared for VM.
dynamic "network_interface" {
for_each = {for idx, val in local.networks: idx => val}
content{
network_id = data.vsphere_network.interfaces[network_interface.key].id
}
}
Data sources are also generated 3 times.
I need to create only interfaces that are declared for this vm and not for all vms. How can i achieve this?
Thank you for answers!
Resource definition:
resource "vsphere_virtual_machine" "vm" {
for_each = var.virtual_machines
name = "terra-${each.key}.${each.value.domain_name}"
resource_pool_id = data.vsphere_host.host.resource_pool_id
datastore_id = data.vsphere_datastore.datastore.id
num_cpus = each.value.num_cpus
memory = each.value.memory
guest_id = data.vsphere_virtual_machine.template[each.key].guest_id
disk {
label = "disk0"
size = data.vsphere_virtual_machine.template[each.key].disks[0].size
thin_provisioned = data.vsphere_virtual_machine.template[each.key].disks[0].thin_provisioned
}
dynamic "network_interface" {
for_each = {for idx, val in local.networks: idx => val}
content{
network_id = data.vsphere_network.interfaces[network_interface.key].id
}
}
clone {
template_uuid = data.vsphere_virtual_machine.template[each.key].id
customize {
linux_options {
host_name = "${each.key}.${each.value.domain_name}"
domain = each.value.domain_name
}
dynamic "network_interface" {
for_each = {for idx, val in local.networks: idx => val}
content {
ipv4_address = network_interface.value.ipv4_address
ipv4_netmask = network_interface.value.ipv4_netmask
}
}
ipv4_gateway = each.value.gateway
}
}
}
Locals:
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
}
]
])
}
Its better to flatten your networks this way, as this will give you map, not list, with keys vmname-ipaddress
:
locals {
networks = merge([
for vm_key, objects in var.virtual_machines : {
for interface in objects.interfaces :
"${vm_key}-${interface.ipv4_address}" => {
network = interface.network
ipv4_address = interface.ipv4_address
ipv4_netmask = interface.ipv4_netmask
}
}]...)
}
then
data "vsphere_network" "interfaces" {
for_each = local.networks
name = each.value.network
datacenter_id = data.vsphere_datacenter.dc.id
}
and finally you get correct NI using the key vmname-ipaddress
in the loop:
dynamic "network_interface" {
for_each = each.value.interfaces
content{
network_id = data.vsphere_network.interfaces["${each.key}-${network_interface.value.ipv4_address}"].id
}
}