Home > Mobile >  Terraform Azurerm - when VMs are not created in az zone compatible region then use availability set.
Terraform Azurerm - when VMs are not created in az zone compatible region then use availability set.

Time:11-16

I want to deploy a bunch of resources only by calling one self written module:

module "transit-gateway-sea" {
  source             = "./modules/transit-gateway"
  location           = "southeastasia"
  vnet_address_space = [local.sea_vnet_address_space]
  subnet_address_spaces = {
    mgmt0 = [cidrsubnets(local.sea_vnet_address_space, 2, 2, 2, 2, )[0]]
    wan0  = [cidrsubnets(local.sea_vnet_address_space, 2, 2, 2, 2, )[1]]
    lan0  = [cidrsubnets(local.sea_vnet_address_space, 2, 2, 2, 2, )[2]]
  }
  bastion_subnet = [cidrsubnets(local.sea_vnet_address_space, 2, 2, 2, 2, )[3]]
  ha_enabled = true
}

Inside of this module a few things happen but the import thing to know is, that based on the region I assign a value to a local, like this:

locals {
  country_code = (var.location == "southeastasia" ? "-sea" :
    var.location == "westeurope" ? "-weu" :
    var.location == "northcentralus" ? "-ncus" :
    var.location == "brazilsouth" ? "-bs" :
    var.location == "northeurope" ? "-neu" :
    ""
  )
  primary_zone = (var.location == "southeastasia" ? "1" :
    var.location == "westeurope" ? "1" :
    var.location == "brazilsouth" ? "1" :
    var.location == "northeurope" ? "1" :
    null
  )
  secondary_zone = (var.location == "southeastasia" ? "2" :
    var.location == "westeurope" ? "2" :
    var.location == "brazilsouth" ? "2" :
    var.location == "northeurope" ? "2" :
    null
  )
}

Please find the code for the VMs and the availability sets and zones below. The secondary vm is only deployed if ha_enabled variable is to true during the module call. Same logic applies somehow to the availability set, but it depends on the region whether Avail Zones are supported in that region or not. If not the Avail Set should be deployed and both VMs should be assigned to this Avail Set.

resource "azurerm_availability_set" "aset" {
  count = local.primary_zone != "1" ? 0 : 1

  name                = "silverpeak-sdwan${local.country_code}-aset"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  lifecycle {
    ignore_changes = [
      tags
    ]
  }
}

resource "azurerm_linux_virtual_machine" "primary-vm" {
  count               = 1
  name                = "silverpeak-sdwan${local.country_code}-primary-vm"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  size                = var.vm_size
  admin_username = "adminuser"
  admin_password = random_password.admin-password-primary.result
  disable_password_authentication = false
  zone                            = local.primary_zone
  encryption_at_host_enabled      = true
  allow_extension_operations      = false
  availability_set_id             = local.primary_zone != "1" ? azurerm_availability_set.aset[count.index].id : null

  network_interface_ids = [
    for nics in azurerm_network_interface.primary-nics : nics.id
  ]

  os_disk {
    name                 = "silverpeak-sdwan${local.country_code}-primary-vm-osdisk"
    caching              = "ReadWrite"
    storage_account_type = var.storage_account_type
  }

  source_image_reference {
    publisher = "silver-peak-systems"
    offer     = "silver_peak_edgeconnect_vwan"
    sku       = "silver_peak_edgeconnect_vwan_8_3_0_14"
    version   = "8.3.0"
  }
  plan {
    name      = "silver_peak_edgeconnect_vwan_8_3_0_14"
    publisher = "silver-peak-systems"
    product   = "silver_peak_edgeconnect_vwan"
  }

  lifecycle {
    ignore_changes = [
      tags
    ]
  }
}


resource "azurerm_linux_virtual_machine" "secondary-vm" {
  count               = var.ha_enabled ? 1 : 0
  name                = "silverpeak-sdwan${local.country_code}-secondary-vm"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  size                = var.vm_size
  admin_username = "adminuser"
  admin_password = random_password.admin-password-secondary.result
  disable_password_authentication = false
  zone                            = local.secondary_zone
  encryption_at_host_enabled      = true
  allow_extension_operations      = false
  availability_set_id             = local.secondary_zone != "2" ? azurerm_availability_set.aset[count.index].id : null

  network_interface_ids = [
    for nics in azurerm_network_interface.secondary-nics : nics.id
  ]

  os_disk {
    name                 = "silverpeak-sdwan${local.country_code}-secondary-vm-osdisk"
    caching              = "ReadWrite"
    storage_account_type = var.storage_account_type
  }

  source_image_reference {
    publisher = "silver-peak-systems"
    offer     = "silver_peak_edgeconnect_vwan"
    sku       = "silver_peak_edgeconnect_vwan_8_3_0_14"
    version   = "8.3.0"
  }
  plan {
    name      = "silver_peak_edgeconnect_vwan_8_3_0_14"
    publisher = "silver-peak-systems"
    product   = "silver_peak_edgeconnect_vwan"
  }

  lifecycle {
    ignore_changes = [
      tags
    ]
  }
}

so based on the location I deploy an availability set or availibility zones. From my point of view this makes absolutely sense but I get I error message which I do not understand. I hope some of you guys can help me. It looks like somehow azurerm_availability_set.aset is empty, but it shouldn't based on the condition in the count parameter. I hope some of you guys can help me.

│ Error: Invalid index
│ 
│   on modules/transit-gateway/vm.tf line 51, in resource "azurerm_linux_virtual_machine" "primary-vm":
│   51:   availability_set_id             = local.primary_zone != "1" ? azurerm_availability_set.aset[count.index].id : null
│     ├────────────────
│     │ azurerm_availability_set.aset is empty tuple
│     │ count.index is 0
│ 
│ The given key does not identify an element in this collection value: the
│ collection has no elements.
╵
╷
│ Error: Invalid index
│ 
│   on modules/transit-gateway/vm.tf line 97, in resource "azurerm_linux_virtual_machine" "secondary-vm":
│   97:   availability_set_id             = local.secondary_zone != "2" ? azurerm_availability_set.aset[count.index].id : null
│     ├────────────────
│     │ azurerm_availability_set.aset is empty tuple
│     │ count.index is 0
│ 
│ The given key does not identify an element in this collection value: the
│ collection has no elements.
╵
##[error]Error: Terraform Plan failed with exit code: 1

CodePudding user response:

I found out what was wrong with the code. So everyone else who is doing similar things with other or same resources double check your condition and double check the logic of your code.

for the availability set resource I did this: count = local.primary_zone != "1" ? 0 : 1

but I should have done this: count = local.primary_zone == "1" ? 0 : 1

and now it works! Now an availability set is created and VMs added automatically when availability zones are not available in a certain region.

  • Related