For_each to iterate over distinct network_interface_ids

Hello,

I have recently upgraded to TF 0.12.19 and replaced count with for_each, as I wanted to build multiple VMs with unique configuration items. Here is part of the code that I modified to use the loop:

resource "azurerm_virtual_machine" "ubuntu" {
name = each.key
for_each = var.u_name
location = var.vm_location
resource_group_name = var.rg_vm
network_interface_ids = values(azurerm_network_interface.unic).*.id
delete_os_disk_on_termination = var.os_disk_attr["os_disk_delete"]
vm_size = each.value

u_name as defined in the variables.tf file:

variable "u_name" {
description = "Defines the VM sizes"
type = map(string)
default = {
dmp-nifi-prod-u-vm = "Standard_D2s_v3"
dmp-es-prod-u-vm = "Standard_D2s_v3"
dmp-kfk-prod-u-vm = "Standard_B2s"
dmp-utl-prod-u-vm = "Standard_B2s"
   }

}

With network_interface_ids = values(azurerm_network_interface.unic).*.id, TF tries to add 4 NICs per VM. I want it to add one NIC per VM. I have referenced the terraform page that describes the use of for_each and values, but I have been unable to make it work.

I will need to use it with the local-exec provisioner as well to pick private IP addresses one at a time to run an Ansible playbook against. This is what I have in the provisioner file:

resource "null_resource" "Ansible4Ubuntu" {
for_each = var.u_name
depends_on = [
azurerm_virtual_machine.ubuntu,
azurerm_network_interface.unic,
]
#triggers = {
#network_interface_ids = values(azurerm_network_interface.unic). <em>.id
#network_interface_ids = join(",", azurerm_network_interface.unic.</em> .id)
#}
provisioner "local-exec" {
command = "sleep 5 ; ansible-playbook -i ${values(azurerm_network_interface.unic).*.id} 
vmlinux-playbook.yml"
   }
}

Any help would be appreciated.

Thanks

Generally, we do not recommend the use of provisioners, specifically local-exec. There are a few other paths you can try that might better trigger the Ansible playbook.

Are you doing installation or configuration with your provisioner? If it is installation, it might be helpful to use Packer to pre-build the image. If it is for configuration, it might be worth adding the ansible-playbook command to cloud-init to run on machine startup and configure it for you.

Second, are you using count to create the azurerm_network_interface resources? If you’re able to attach the configuration, it would help us debug. You might still need to use count in the azurerm_virtual_machine resource. If you want to stick with for_each, you might have to do some special list comprehension to extract the index of the map elements instead of the list elements. It adds the four nics because of the *.id syntax, which adds the entire list of nics.

Let us know!

Hi Rosemary!

Thanks for your reply.

No, I am not using count anymore. I am using for_each to create azurerm_network_interface. I’d like to retrieve the network_interface_ids one at a time and assign it to the VM being created. I also want to retrieve the private IP address for each interface and pass it to the ansible-playbook command.

The reason I opted for for_each is to be able to use a list of maps (hostname = VM size) as depicted in the variables.tf file above. Is there an alternative to values(azurerm_network_interface.unic).*.id that I can use to make it work as desired? I have the triggers block turned off. Can I use a combination of triggers and, perhaps, elements or values or join to make it work?

Thank you.