terraform { required_version = "~> 0.12.21" required_providers { azurerm = "~> 1.44" } } resource "azurerm_virtual_machine" "azvm" { count = length(var.vms) name = var.vms[count.index].name resource_group_name = var.vms[count.index].resource_group_name location = var.vms[count.index].location network_interface_ids = [for nic in var.vms[count.index].nics: azurerm_network_interface.nic[join("-nic", [var.vms[count.index].name, index(var.vms[count.index].nics, nic)])].id] vm_size = var.vms[count.index].vm_size #Standard_D2s_v3, Standard_B2s availability_set_id = azurerm_availability_set.avset[var.vms[count.index].avset.name].id tags = var.vms[count.index].tags delete_os_disk_on_termination = try(var.vms[count.index].delete_os_disk_on_termination, true) delete_data_disks_on_termination = try(var.vms[count.index].delete_data_disks_on_termination, true) #zones = try(var.vms[count.index].zones, null) storage_os_disk { name = join("-", [var.vms[count.index].name, "disk"]) caching = var.vms[count.index].storage_os_disk.caching #None, ReadOnly or ReadWrite create_option = var.vms[count.index].storage_os_disk.create_option #Attach, FromImage disk_size_gb = var.vms[count.index].storage_os_disk.disk_size_gb os_type = var.vms[count.index].storage_os_disk.os_type #Linux or Windows } dynamic "os_profile" { for_each = var.vms[count.index].os_profile content { computer_name = var.vms[count.index].name admin_username = try(os_profile.value.admin_username, "") != "" ? os_profile.value.admin_username : "master" admin_password = try(os_profile.value.admin_password, null) } } dynamic "os_profile_linux_config" { for_each = try(var.vms[count.index].os_profile_linux_config, []) content { disable_password_authentication = os_profile_linux_config.value.disable_password_authentication dynamic "ssh_keys" { for_each = os_profile_linux_config.value.disable_password_authentication ? os_profile_linux_config.value.ssh_keys : {} content { key_data = try(ssh_keys.value.file, "") != "" ? file("${ssh_keys.value.file}") : var.default_ssh_pubkey path = try(ssh_keys.value.dst_path, "") != "" ? ssh_keys.value.dst_path : format("/home/%s/.ssh/authorized_keys", "master") } } } } dynamic "os_profile_windows_config" { for_each = try(var.vms[count.index].os_profile_windows_config, []) content { provision_vm_agent = os_profile_windows_config.value.provision_vm_agent enable_automatic_upgrades = os_profile_windows_config.value.enable_automatic_upgrades timezone = os_profile_windows_config.value.timezone #https://jackstromberg.com/2017/01/list-of-time-zones-consumed-by-azure/ winrm { protocol = os_profile_windows_config.value.protocol #HTTP or HTTPS certificate_url = os_profile_windows_config.value.certificate_url } } } dynamic "plan" { for_each = try(var.vms[count.index].plan, []) content { name = plan.value.name publisher = plan.value.publisher product = plan.value.product } } dynamic "storage_data_disk" { for_each = try(var.vms[count.index].storage_data_disk, []) content { name = storage_data_disk.value.name caching = try(storage_data_disk.value.caching, "ReadOnly") #None, ReadOnly or ReadWrite create_option = try(storage_data_disk.value.create_option, "Empty") #Attach, FromImage and Empty disk_size_gb = storage_data_disk.value.disk_size_gb lun = storage_data_disk.value.lun } } dynamic "storage_image_reference" { for_each = var.vms[count.index].storage_image_reference content { publisher = storage_image_reference.value.publisher offer = storage_image_reference.value.offer sku = storage_image_reference.value.sku version = storage_image_reference.value.version id = try(storage_image_reference.value.id, null) } } depends_on = [azurerm_marketplace_agreement.accept, var.azvm_depends_on] } locals { # flatten ensures that this local value is a flat list of objects, rather # than a list of lists of objects. avsets = flatten([ for vm in var.vms : { name = vm.avset.name location = vm.location resource_group_name = try(vm.avset.resource_group_name, vm.resource_group_name) platform_update_domain_count = try(vm.avset.platform_update_domain_count, 2) platform_fault_domain_count = try(vm.avset.platform_fault_domain_count, 2) managed = try(vm.avset.managed, true) #true => Aligned, false => Classic tags = try(vm.avset.tags, vm.tags) } ]) } resource "azurerm_availability_set" "avset" { for_each = { for avs in local.avsets: avs.name => avs... } name = each.value[0].name location = each.value[0].location resource_group_name = each.value[0].resource_group_name platform_update_domain_count = each.value[0].platform_update_domain_count platform_fault_domain_count = each.value[0].platform_fault_domain_count managed = each.value[0].managed tags = each.value[0].tags } locals { # flatten ensures that this local value is a flat list of objects, rather # than a list of lists of objects. images = flatten([ for vm in var.vms : [ for image in vm.storage_image_reference : { name = join("-", [image.publisher, image.offer, image.sku]) publisher = image.publisher offer = image.offer plan = image.sku } ] ]) } resource "azurerm_marketplace_agreement" "accept" { for_each = { for image in local.images: image.name => image... } publisher = each.value[0].publisher offer = each.value[0].offer plan = each.value[0].plan } locals { # flatten ensures that this local value is a flat list of objects, rather # than a list of lists of objects. nics = flatten([ for vm in var.vms : [ for nic in vm.nics : { name = join("-nic", [vm.name, index(vm.nics, nic)]) location = vm.location resource_group_name = nic.resource_group_name enable_ip_forwarding = try(nic.enable_ip_forwarding, false) enable_accelerated_networking = try(nic.enable_accelerated_networking, false) tags = nic.tags nsg = nic.nsg subnet = nic.subnet ip_configuration = { "name" = "${join("-nic", [vm.name, index(vm.nics, nic)])}-ipc" "private_ip_address_allocation" = try(nic.ip_configuration.private_ip_address_allocation, "Static") "private_ip_address_version" = try(nic.ip_configuration.private_ip_address_version, "IPv4") "private_ip_address" = try(nic.ip_configuration.private_ip_address_allocation, "Static") == "Static" ? nic.ip_configuration.private_ip_address : null "public_ip_address_id" = try(nic.ip_configuration.public_ip_address_id, null) } } ] ]) } resource "azurerm_network_interface" "nic" { for_each = {for nic in local.nics: nic.name => nic} name = each.value.name location = each.value.location resource_group_name = each.value.resource_group_name enable_ip_forwarding = each.value.enable_ip_forwarding enable_accelerated_networking = each.value.enable_accelerated_networking network_security_group_id = data.azurerm_network_security_group.nsg[each.value.name].id tags = each.value.tags ip_configuration { name = each.value.ip_configuration.name subnet_id = data.azurerm_subnet.sub[each.value.name].id private_ip_address_allocation = each.value.ip_configuration.private_ip_address_allocation private_ip_address_version = each.value.ip_configuration.private_ip_address_version private_ip_address = try(each.value.ip_configuration.private_ip_address, null) public_ip_address_id = try(each.value.ip_configuration.public_ip_address_id, null) } } data "azurerm_network_security_group" "nsg" { for_each = {for nic in local.nics: nic.name => nic} name = each.value.nsg.name resource_group_name = each.value.nsg.resource_group_name depends_on = [var.azvm_depends_on] } data "azurerm_subnet" "sub" { for_each = {for nic in local.nics: nic.name => nic} name = each.value.subnet.name virtual_network_name = each.value.subnet.virtual_network_name resource_group_name = each.value.subnet.resource_group_name depends_on = [var.azvm_depends_on] }