FOR loop with IF condition checking array

Hello everyone, probably for someone super easy task, but for me few hours of struggling.
Very simple request.
I have list of VMs in locals i.e.

locals {
  vms = {
    MY-VM1 = {
      vm_name             = "MY-VM1"
      computer_name       = "MY-VM1"
      resource_group_name = azurerm_resource_group.rg["RG-Servers"].name
      location            = azurerm_resource_group.rg["RG-Servers"].location
   },
   MY-VM2 = {
      vm_name             = "MY-VM2"
      computer_name       = "MY-VM2"
      resource_group_name = azurerm_resource_group.rg["RG-Servers"].name
      location            = azurerm_resource_group.rg["RG-Servers"].location
   }
 }
}

and then, I would like to install extension on VM, which I will specify

resource "azurerm_virtual_machine_extension" "vm_ext_ama" {
  for_each = {
    for vm_name, vm in local.vms : vm_name => vm
    if contains(["MY-VM1"], vm) != null
  }

 # Resource specification goes here.
}

I would like to have condition, to deploy extension only on VMs, I will specify.
So in this case using IF with function contains.

Thank you very much for any advice, because for now, TF completely ignores that condition :slight_smile:

To deploy an extension only on specific VMs, adjust the for_each in your azurerm_virtual_machine_extension resource to iterate over VMs whose names are in a predefined list of target VMs. Use the contains function to check if the VM’s name is in the list and include it in the loop accordingly.

Well, that’s what I am trying to achieve but I am failing.
If you could post working example, that would appreciated a lot.

To achieve your goal of conditionally applying the azurerm_virtual_machine_extension resource to a subset of VMs specified in your locals block, you can adjust your Terraform configuration. The key is to use a more suitable conditional logic that filters the local.vms map based on a list of VM names for which you want to apply the extension.

Your current approach with contains(["MY-VM1"], vm) != null isn’t working as expected because contains is designed to check if a given value is present in a list or a set, and vm in your loop is a map, not a single value. Instead, you can use the vm_name attribute within each vm map to check against your list of target VM names.

Here’s how you can adjust your code:

hclCopy code

locals {
  vms = {
    MY-VM1 = {
      vm_name             = "MY-VM1"
      computer_name       = "MY-VM1"
      resource_group_name = azurerm_resource_group.rg["RG-Servers"].name
      location            = azurerm_resource_group.rg["RG-Servers"].location
    },
    MY-VM2 = {
      vm_name             = "MY-VM2"
      computer_name       = "MY-VM2"
      resource_group_name = azurerm_resource_group.rg["RG-Servers"].name
      location            = azurerm_resource_group.rg["RG-Servers"].location
    }
  }

  target_vms = ["MY-VM1"] # List of VMs to install the extension on
}

resource "azurerm_virtual_machine_extension" "vm_ext_ama" {
  for_each = {for vm_name, vm in local.vms : vm_name => vm if contains(local.target_vms, vm_name)}

  # Resource specification goes here.
  # Use each.key for the VM name and each.value for the VM properties
}

In this revised version:

  • We define a new local variable target_vms that contains a list of VM names for which you want to apply the extension.
  • In the for_each expression within the azurerm_virtual_machine_extension resource, we use a conditional check if contains(local.target_vms, vm_name) to filter the VMs. This way, the extension resource is only created for the VMs listed in local.target_vms.
  • The contains function checks if vm_name is in the list of local.target_vms. If it is, the VM is included in the resulting map for for_each, and the extension resource is applied to it.

This approach should correctly apply the extension only to the VMs you specify in the local.target_vms list.

1 Like

Hello rtwofle,

thank you very much for this explanation!
But for that I was confused, why it is not working, if I am checking value against list, even using vm_name.
The only difference is, you have specified it in locals, while I was inserting that list directly.
And I was also trying checking that using vm_name as you suggested.

The whole problem is, I have never removed != null from condition, which was causing omitting the condition.
So, the condition you have suggested me, it is working, even using list directly as do
i.e. if contains(["MY-VM1"], vm_name).

Thank you again, you have solved

1 Like

Cool man great work!