azureterraformterraform-provider-azureterraform-modules

how to iterate list of map objects in terraform


I am trying write a for loop to get the disks map object for below terraform code. However I am getting "This object does not have an attribute named "disks" " error at the time of terraform plan.

locals {
  image = {
    nodes = {
      vm1 = {
        name = "vm1"
        vm_num = "1"
        networks = {
          nic1 = {
            name = "vm1-nic1"
            subnet = "subnet1"
          }
          nic2 = {
            name = "vm1-nic2"
            subnet = "subnet2"
          }
        }
      },
      vm2 = {
        name = "vm2"
        vm_num = "2"
        networks = {
          nic1 = {
            name = "vm2-nic1"
            subnet = "subnet2"

          }
          nic2 = {
            name = "vm2-nic2"
            subnet = "subnet2"

          }
        }
        disks ={
          disk1 = {
            "lun" = "0"
            "size" = "1024"
          },
          disk2 = {
            "lun" = "1"
            "size" = "1024"
          }
        }
      }
    }
  }
}

output "iterate-networks" {
  value = {
    for_each = { for vm in flatten([for vm_name, vm  in local.image.nodes : [for nic_name, nic in vm.networks : { vm_number = vm.vm_num, vm_name = vm_name, nic_name = nic_name, nic_value = nic.name, subnet_name = nic.subnet }]]) : "${vm.vm_name}-${vm.nic_name}" => vm }
  }
}


output "iterate-disks" {
  value = {
    for_each = { for vm in flatten([for vm_name, vm  in local.image.nodes : [for disk_name, disk in vm.disks : { vm_number = vm.vm_num, disk_name= disk_name, disk_lun = disk.lun, disk_size = disk.size }]]) : "${vm.vm_name}-${vm.num}" => vm }
  }
}

Error while terraform plan:

Error: Unsupported attribute
    │ 
    │   on provider.tf line 136, in output "iterate-disks":
    │  136:     for_each = { for vm in flatten([for vm_name, vm  in local.image.nodes : [for disk_name, disk in vm.disks : { vm_number = vm.vm_num, disk_name= disk_name, disk_lun = disk.lun, disk_size = disk.size }]]) : "${vm.vm_name}-${vm.nic_name}" => vm }
    │ 
    │ This object does not have an attribute named "disks".

can someone throw some light on the fix ? Thank You in advance.


Solution

  • disks is only in vm2, not in vm1, so you have to check for the lack of disks in each iteration. You can do this using lookup as follows:

    output "iterate-disks" {
      value = {
        for_each = { 
          for vm in flatten([
              for vm_name, vm  in local.image.nodes : [
                  for disk_name, disk in lookup(vm, "discs", {}) : { 
                      vm_number = vm.vm_num
                      disk_name= disk_name
                      disk_lun = disk.lun
                      disk_size = disk.size 
                  }
          ]
          ]
        ) : "${vm.vm_name}-${vm.nic_name}" => vm }
      }
    }