0
votes

I wrote a script to create Azure VM using terraform. Script is flexible to take the OS as input. Now there are some attributes in azurerm_virtual_machine resource block which are specific to OS. How to use a condition like if windows use os_profile_windows_config{} or if OS is linux use os_profile_linux_config{}.

Normal conditional statements didn't work as this attributes are not taking any values directly by using = .

resource "azurerm_virtual_machine" "vmdeploy" {
  count = "${var.count_of_VMs}"
  name = "${var.vm_name}-${count.index}"
  resource_group_name = "${azurerm_resource_group.deployrg.name}"
  availability_set_id = "${azurerm_availability_set.avset.id}"
  location = "${azurerm_resource_group.deployrg.location}"
  network_interface_ids = ["${element(azurerm_network_interface.nic.*.id, count.index)}"]
  vm_size = "Standard_DS1_v2"

  storage_image_reference{
    publisher = "${var.OS_Image_Publisher}"
    offer = "${var.OS_Image_Offer}"
    sku = "${var.OS_Image_Sku}"
    version = "latest"
  }
  storage_os_disk{
    name = "${var.vm_name}-${count.index}-osdisk"
    caching = "ReadWrite"
    managed_disk_type = "Standard_LRS"
    create_option = "FromImage"
  }

  storage_data_disk {
    name = "${element(azurerm_managed_disk.mdisk.*.name, count.index)}"
    managed_disk_id = "${element(azurerm_managed_disk.mdisk.*.id, count.index)}"
    create_option = "Attach"
    lun = 1
    disk_size_gb = "${element(azurerm_managed_disk.mdisk.*.disk_size_gb, count.index)}"
  }

  os_profile {
    computer_name = "${var.vm_name}-${count.index}"
    admin_username = "XXXXXXXXXXXX"
    admin_password = "XXXXXXXXXXXX"
  }

  os_profile_windows_config {

  }
}

I am trying to find a way to use condition here to use respective config attribute based on OS version which is provided as input.

1
you probably need to have 2 almost identical resources and condition entire resources depending on OS. i'm not saying it the only way, but it would work, most likely - 4c74356b41
which terraform version? pre- or post- 0.12? - Giulio Vian
Giulio Vian, I am using pre-0.12 version, - Vishnu

1 Answers

0
votes

This is not possible pre terraform-0.12. This is possible with dynamic blocks in version 0.12.

provider "azurerm" {
  version = "~>2.19.0"
  features {}
}

variable "image" {
  type = map
  default = {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }
}

locals {
  _is_microsoft = substr(lookup(var.image, "publisher", "value_not_declared"), 0, 9) == "Microsoft" ? true : false
  is_linux      = ! local._is_microsoft ? { empty = true } : {}
  is_windows    = local._is_microsoft ? { empty = true } : {}
}

resource "azurerm_resource_group" "rg" {
  name     = "rg"
  location = "east us"
}

resource "azurerm_virtual_network" "rg" {
  name                = "-network"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "subnet" {
  name                 = "subnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.rg.name
  address_prefixes     = ["10.10.10.0/24"]
}

resource "azurerm_network_interface" "rg" {
  name                = "nic"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "ipconfig"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "rg" {
  name                  = "-vm"
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.rg.id]
  vm_size               = "Standard_D2_v3"

  storage_image_reference {
    publisher = lookup(var.image, "publisher")
    offer     = lookup(var.image, "offer")
    sku       = lookup(var.image, "sku")
    version   = lookup(var.image, "version")
  }
  storage_os_disk {
    name              = "disk1"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }
  os_profile {
    computer_name  = "computer"
    admin_username = "localadmin"
    admin_password = "donotuserthispassword123!"
  }

  dynamic "os_profile_linux_config" {
    for_each = local.is_linux

    content {
      disable_password_authentication = false
    }
  }

  dynamic "os_profile_windows_config" {
    for_each = local.is_windows

    content {
      provision_vm_agent = true
    }
  }
}

Note the azurerm team decided this was not a good idea and split out the resources into two different types. Use azurerm_linux_virtual_machine or azurerm_windows_virtual_machine. Build a module with a single interface then use a count to pick which resource to build either windows or linux.