Using below terraform code. main.tf file is as below
data "azurerm_resource_group" "tf-rg-external" {
name = var.rg_name
}
data "azurerm_virtual_network" "tf-vn" {
name = var.vnet_name
resource_group_name = var.rg_name
}
# Reference existing subnet
data "azurerm_subnet" "tf-sn" {
name = var.subnet_name
virtual_network_name = data.azurerm_virtual_network.tf-vn.name
resource_group_name = var.rg_name
}
module "sql_vm" {
source = "Azure/compute/azurerm"
location = data.azurerm_resource_group.tf-rg-external.location
vnet_subnet_id = data.azurerm_virtual_network.tf-vn.subnets
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
admin_password = var.admin_password
admin_username = var.admin_username
boot_diagnostics = var.boot_diagnostics
boot_diagnostics_sa_type = var.boot_diagnostics_sa_type
# data_disk = var.data_disk
# data_disk_size_gb = var.data_disk_size_gb
# data_sa_type = var.data_sa_type
delete_os_disk_on_termination = var.delete_os_disk_on_termination
enable_accelerated_networking = var.enable_accelerated_networking
# flag is_windows_image is required only when you use a custom image to spin up a VM
# is_windows_image
# flag vm_os_id is required only when you are using custom image
# you need to provide id of your custom image
# vm_os_id
nb_instances = var.nb_instances
#nb_public_ip = var.nb_public_ip
public_ip_address_allocation = var.public_ip_address_allocation
storage_account_type = var.storage_account_type
vm_hostname = var.vm_hostname
vm_os_offer = var.vm_os_offer
vm_os_publisher = var.vm_os_publisher
# vm_os_simple is to be used is you do not wish to specify offer, publisher and sku
# vm_os_simple = UbuntuServer, WindowsServer, RHEL, openSUSE-Leap, CentOS, Debian, CoreOS and SLES
vm_os_sku = var.vm_os_sku
vm_os_version = var.vm_os_version
vm_size = var.vm_size
}
my variables.tf file is as below:
variable "public_ip_address_allocation" {
type = string
default = "Dynamic"
}
variable "storage_account_type" {
type = string
default = "Standard_LRS"
}
variable "vm_hostname" {
type = string
default = "testvm"
}
variable "vm_os_offer" {
type = string
default = "WindowsServer"
}
variable "vm_os_publisher" {
type = string
default = "MicrosoftWindowsServer"
}
variable "vm_os_sku" {
type = string
default = "2012-R2-Datacenter"
}
variable "vm_os_version" {
type = string
default = "latest"
}
variable "vm_size" {
type = string
default = "Standard_B1ms"
}
variable "admin_password" {
type = string
default = "Symphony12#$%"
}
variable "admin_username" {
type = string
default = "devopsadmin"
}
variable "boot_diagnostics" {
type = bool
default = "true"
}
variable "boot_diagnostics_sa_type" {
type = string
default = "Standard_LRS"
}
# variable "data_disk" {
# type = bool
# default ="false"
# }
# variable "data_disk_size_gb" {
# type = number
# default = 0
# }
# variable "data_sa_type" {
# type = string
# }
variable "delete_os_disk_on_termination" {
type = bool
default = true
}
variable "enable_accelerated_networking" {
type = bool
default = false
}
variable "nb_instances" {
type = number
default = 2
}
# variable "nb_public_ip" {
# type = bool
# default = "1"
# }
# variable "location" {
# type = string
# }
# variable "vnet_subnet_id" {
# type = string
# }
variable "rg_name" {
type = string
default = "nxt-grp-prd-manage-rgp-au-se"
}
variable "subnet_name" {
type = string
default = "subnet_1"
}
variable "vnet_name" {
type = string
default = "virtual_network_1"
}
When I run terraform plan, it reports Error below:
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
data.azurerm_virtual_network.tf-vn: Refreshing state...
data.azurerm_resource_group.tf-rg-external: Refreshing state...
data.azurerm_subnet.tf-sn: Refreshing state...
------------------------------------------------------------------------
Warning: "public_ip_address_allocation": [DEPRECATED] this property has been deprecated in favor of `allocation_method` to better match the api
on .terraform/modules/sql_vm/Azure-terraform-azurerm-compute-fb014dd/main.tf line 248, in resource "azurerm_public_ip" "vm":
248: resource "azurerm_public_ip" "vm" {
Warning: "public_ip_address_allocation": [DEPRECATED] this property has been deprecated in favor of `allocation_method` to better match the api
on .terraform/modules/sql_vm/Azure-terraform-azurerm-compute-fb014dd/main.tf line 248, in resource "azurerm_public_ip" "vm":
248: resource "azurerm_public_ip" "vm" {
Error: domain_name_label must contain only lowercase alphanumeric characters, numbers and hyphens. It must start with a letter and end only with a number or letter
on .terraform/modules/sql_vm/Azure-terraform-azurerm-compute-fb014dd/main.tf line 248, in resource "azurerm_public_ip" "vm":
248: resource "azurerm_public_ip" "vm" {
I would like to have an ability to override what it is in default module, something like below
domain_name_label = "false"
Unfortunately, when I do so in my main file, I get error like below:
Error: Unsupported argument
on main.tf line 48, in module "sql_vm":
48: domain_name_label = "false"
An argument named "domain_name_label" is not expected here.
So, is there not anyway to override, as this is an out-of-box configuration, I would be much happier to see it working.
I would like to have an ability to override what it is in default module, something like below
For that, the tf module should declare that as a variable. Your module Azure/compute/azurerm doesn't have a variable defined for domain_name_label.
Taking a step back and looking at your original issue: Look at the following block of code from this module:
https://github.com/Azure/terraform-azurerm-compute/blob/master/main.tf#L248
resource "azurerm_public_ip" "vm" {
count = "${var.nb_public_ip}"
name = "${var.vm_hostname}-${count.index}-publicIP"
location = "${var.location}"
resource_group_name = "${azurerm_resource_group.vm.name}"
public_ip_address_allocation = "${var.public_ip_address_allocation}"
domain_name_label = "${element(var.public_ip_dns, count.index)}"
tags = "${var.tags}"
}
Please set a value for public_ip_dns in your call to this module. That is expected to fix your issue.
Example:
(Note the line public_ip_dns = ["my-new-good-vm"]):
module "sql_vm" {
source = "Azure/compute/azurerm"
location = data.azurerm_resource_group.tf-rg-external.location
vnet_subnet_id = data.azurerm_virtual_network.tf-vn.subnets
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
admin_password = var.admin_password
admin_username = var.admin_username
public_ip_dns = ["my-new-good-vm"]
boot_diagnostics = var.boot_diagnostics
boot_diagnostics_sa_type = var.boot_diagnostics_sa_type
# data_disk = var.data_disk
# data_disk_size_gb = var.data_disk_size_gb
# data_sa_type = var.data_sa_type
delete_os_disk_on_termination = var.delete_os_disk_on_termination
enable_accelerated_networking = var.enable_accelerated_networking
# flag is_windows_image is required only when you use a custom image to spin up a VM
# is_windows_image
# flag vm_os_id is required only when you are using custom image
# you need to provide id of your custom image
# vm_os_id
nb_instances = var.nb_instances
#nb_public_ip = var.nb_public_ip
public_ip_address_allocation = var.public_ip_address_allocation
storage_account_type = var.storage_account_type
vm_hostname = var.vm_hostname
vm_os_offer = var.vm_os_offer
vm_os_publisher = var.vm_os_publisher
# vm_os_simple is to be used is you do not wish to specify offer, publisher and sku
# vm_os_simple = UbuntuServer, WindowsServer, RHEL, openSUSE-Leap, CentOS, Debian, CoreOS and SLES
vm_os_sku = var.vm_os_sku
vm_os_version = var.vm_os_version
vm_size = var.vm_size
}
Related
I'm running a "terraform plan" against my Linux VM and I'm receiving the following error:
Error: Invalid value for module argument
│
│ on compute_lin_vm.tf line 10, in module "vm-ansiblecontroller":
│ 10: nic_id = module.vm-ansiblecontroller.nic_id
│
│ The given value is not suitable for child module variable "nic_id" defined at
│ .terraform/modules/vm-ansiblecontroller/virtual-machine/linux/variables.tf:83,1-18: list of string required.
I haven't included any code from my RGs & vNets, as I'm hoping what I have included is enough to solve this.
I've set nic_id type to list(string) and it's still giving me the error listed above, I must be missing something simple.
module "vm-ansiblecontroller" {
resource_group_name = module.rg-ansiblecontroller.resource_group_name
location = local.location
linux_machine_name = "linux-test1"
tags = var.tags
nic_id = module.vm-ansiblecontroller.nic_id
subnet_id = module.subnet-networkcore.subnet_id
virtual_machine_size = "Standard_D2"
admin_username = "jpadmin"
admin_ssh_public_key = file("~/.ssh/id_rsa.pub")
source_image_publisher = "Canonical"
source_image_offer = "UbuntuServer"
source_image_sku = "16.04-LTS"
source_image_version = "latest"
operating_system_disk_cache = "ReadWrite"
operating_system_disk_type = "Standard_LRS"
ip_configuration_name = "internal"
private_ip_address_allocation = "Dynamic"
public_ip_allocation_method = "Static"
public_ip_sku = "Standard"
}
modules/virtualmachine/main.tf
# Linux Virtual Machine
resource "azurerm_linux_virtual_machine" "vm-linux" {
name = var.linux_machine_name
location = var.location
resource_group_name = var.resource_group_name
tags = var.tags
size = var.virtual_machine_size
admin_username = var.admin_username
disable_password_authentication = true
# network_interface_ids = [azurerm_network_interface.nic-linux.id]
network_interface_ids = var.nic_id
admin_ssh_key {
username = var.admin_username
public_key = var.admin_ssh_public_key
}
source_image_reference {
publisher = var.source_image_publisher
offer = var.source_image_offer
sku = var.source_image_sku
version = var.source_image_version
}
os_disk {
caching = var.operating_system_disk_cache
storage_account_type = var.operating_system_disk_type
}
}
# Network Interfaces for Linux VM
resource "azurerm_network_interface" "nic-linux" {
name = var.linux_machine_name
location = var.location
resource_group_name = var.resource_group_name
tags = var.tags
ip_configuration {
name = var.ip_configuration_name
# subnet_id = azurerm_subnet.subnet.id
subnet_id = var.subnet_id
private_ip_address_allocation = var.private_ip_address_allocation
public_ip_address_id = azurerm_public_ip.pip-linux.id
}
}
resource "azurerm_public_ip" "pip-linux" {
name = var.linux_machine_name
location = var.location
resource_group_name = var.resource_group_name
tags = var.tags
allocation_method = var.public_ip_allocation_method
sku = var.public_ip_sku
}
modules/virtualmachine/variables.tf
# VM Name
variable "linux_machine_name" {
description = "Linux Virtual Machine Name - If left blank generated from metadata module"
type = string
default = ""
}
variable "resource_group_name" {
description = "Resource group name"
type = string
}
variable "location" {
description = "Azure region"
type = string
}
variable "tags" {
description = "tags to be applied to resources"
type = map(string)
}
# VM Size
variable "virtual_machine_size" {
description = "Instance size to be provisioned"
type = string
}
variable "admin_username" {
description = "names to be applied to resources"
type = string
}
variable "admin_ssh_public_key" {
description = "(Linux) Public SSH Key - Generated if left blank"
type = string
default = ""
sensitive = true
}
# Operating System
variable "source_image_publisher" {
description = "Operating System Publisher"
type = string
}
variable "source_image_offer" {
description = "Operating System Name"
type = string
}
variable "source_image_sku" {
description = "Operating System SKU"
type = string
}
variable "source_image_version" {
description = "Operating System Version"
type = string
default = "latest"
}
# Operating System Disk
variable "operating_system_disk_cache" {
description = "Type of caching to use on the OS disk - Options: None, ReadOnly or ReadWrite"
type = string
default = "ReadWrite"
}
variable "operating_system_disk_type" {
description = "Type of storage account to use with the OS disk - Options: Standard_LRS, StandardSSD_LRS or Premium_LRS"
type = string
default = "StandardSSD_LRS"
}
variable "ip_configuration_name" {
description = "ip configuration name"
type = string
default = ""
}
# Networking
variable "nic_id" {
type = list(string)
description = "ID of the nic"
}
variable "subnet_id" {
type = string
description = "ID of the subnet"
}
variable "private_ip_address_allocation" {
type = string
description = "Private ip allocation method"
}
variable "public_ip_allocation_method" {
type = string
description = "Public ip allocation method"
}
variable "public_ip_sku" {
description = "SKU to be used with this public IP - Basic or Standard"
type = string
default = "Standard"
}
modules/virtualmachine/outputs.tf
output "nic_id" {
description = "ids of the vm nics provisoned."
value = azurerm_network_interface.nic-linux.id
}
You would have to change the nic_id input in the Ansible controller module to pass the value as:
nic_id = [module.vm-ansiblecontroller.nic_id]
This is because the input variable nic_id is expecting a list of strings and you are passing a single string based on the output from another module.
I am trying to provision both a Rocky VM (which costs $ per hour) and an Ubuntu VM (which doesn't)
Rocky VM requires the plan block nested in resource "azurerm_linux_virtual_machine
Ubuntu doesn't require the block
I'm getting the following error when running terraform plan:
Error: Missing required argument
│
│ on compute_lin_vm.tf line 43, in module "vm-jpdev":
│ 43: module "vm-jpdev" {
│
│ The argument "plan_name" is required, but no definition was found.
╵
╷
│ Error: Missing required argument
│
│ on compute_lin_vm.tf line 43, in module "vm-jpdev":
│ 43: module "vm-jpdev" {
│
│ The argument "plan_product" is required, but no definition was found.
╵
╷
│ Error: Missing required argument
│
│ on compute_lin_vm.tf line 43, in module "vm-jpdev":
│ 43: module "vm-jpdev" {
│
│ The argument "plan_publisher" is required, but no definition was found.
Linux VMs modules block
module "vm-ansiblecontroller" {
resource_group_name = module.rg-ansiblecontroller.resource_group_name
location = local.location
linux_machine_name = "linux-test1"
tags = var.tags
nic_id = [module.vm-ansiblecontroller.nic_id]
subnet_id = module.subnet-networkcore.subnet_id
virtual_machine_size = "Standard_D2"
admin_username = "jpadmin"
admin_ssh_public_key = file("~/.ssh/id_rsa.pub")
source_image_publisher = "procomputers"
source_image_offer = "rocky-lnx-8-latest"
source_image_sku = "rocky-linux-8-latest"
source_image_version = "8.5.20220222"
plan_name = "rocky-linux-8-latest"
plan_product = "rocky-lnx-8-latest"
plan_publisher = "procomputers"
operating_system_disk_cache = "ReadWrite"
operating_system_disk_type = "Standard_LRS"
ip_configuration_name = "internal"
private_ip_address_allocation = "Dynamic"
public_ip_allocation_method = "Static"
public_ip_sku = "Standard"
depends_on = [
module.rg-networkcore,
module.vnet-networkcore,
module.subnet-networkcore
]
}
module "vm-jpdev" {
resource_group_name = module.rg-jpdev-vm.resource_group_name
location = local.location
linux_machine_name = "linux-test2"
tags = var.tags
nic_id = [module.vm-jpdev.nic_id]
subnet_id = module.subnet-networkcore.subnet_id
virtual_machine_size = "Standard_D2"
admin_username = "jpadmin"
admin_ssh_public_key = file("~/.ssh/id_rsa.pub")
source_image_publisher = "Canonical"
source_image_offer = "UbuntuServer"
source_image_sku = "16.04-LTS"
source_image_version = "latest"
operating_system_disk_cache = "ReadWrite"
operating_system_disk_type = "Standard_LRS"
ip_configuration_name = "internal"
private_ip_address_allocation = "Dynamic"
public_ip_allocation_method = "Static"
public_ip_sku = "Standard"
}
modules/virtualmachine/linux/main.tf
# Linux Virtual Machine
resource "azurerm_linux_virtual_machine" "vm-linux" {
name = var.linux_machine_name
location = var.location
resource_group_name = var.resource_group_name
tags = var.tags
size = var.virtual_machine_size
admin_username = var.admin_username
disable_password_authentication = true
network_interface_ids = var.nic_id
admin_ssh_key {
username = var.admin_username
public_key = var.admin_ssh_public_key
}
source_image_reference {
publisher = var.source_image_publisher
offer = var.source_image_offer
sku = var.source_image_sku
version = var.source_image_version
}
# plan {
# name = var.plan_name
# product = var.plan_product
# publisher = var.plan_publisher
# }
dynamic "plan" {
for_each = var.plan_product == "rocky-lnx-8-latest" ? [1] : []
content {
name = var.plan_name
product = var.plan_product
publisher = var.plan_publisher
}
}
os_disk {
caching = var.operating_system_disk_cache
storage_account_type = var.operating_system_disk_type
}
}
# Network Interfaces for Linux VM
resource "azurerm_network_interface" "nic-linux" {
name = var.linux_machine_name
location = var.location
resource_group_name = var.resource_group_name
tags = var.tags
ip_configuration {
name = var.ip_configuration_name
subnet_id = var.subnet_id
private_ip_address_allocation = var.private_ip_address_allocation
public_ip_address_id = azurerm_public_ip.pip-linux.id
}
}
resource "azurerm_public_ip" "pip-linux" {
name = var.linux_machine_name
location = var.location
resource_group_name = var.resource_group_name
tags = var.tags
allocation_method = var.public_ip_allocation_method
sku = var.public_ip_sku
}
modules/virtualmachine/linux/variables.tf
# VM Name
variable "linux_machine_name" {
description = "Linux Virtual Machine Name - If left blank generated from metadata module"
type = string
default = ""
}
variable "resource_group_name" {
description = "Resource group name"
type = string
}
variable "location" {
description = "Azure region"
type = string
}
variable "tags" {
description = "tags to be applied to resources"
type = map(string)
}
# VM Size
variable "virtual_machine_size" {
description = "Instance size to be provisioned"
type = string
}
variable "admin_username" {
description = "names to be applied to resources"
type = string
}
variable "admin_ssh_public_key" {
description = "(Linux) Public SSH Key - Generated if left blank"
type = string
default = ""
sensitive = true
}
# Operating System
variable "source_image_publisher" {
description = "Operating System Publisher"
type = string
}
variable "source_image_offer" {
description = "Operating System Name"
type = string
}
variable "source_image_sku" {
description = "Operating System SKU"
type = string
}
variable "source_image_version" {
description = "Operating System Version"
type = string
default = "latest"
}
# Plan Block Variables
variable "plan_name" {
description = "Plan Name"
type = string
}
variable "plan_product" {
description = "Plan Product"
type = string
}
variable "plan_publisher" {
description = "Plan Publisher"
type = string
}
# Operating System Disk
variable "operating_system_disk_cache" {
description = "Type of caching to use on the OS disk - Options: None, ReadOnly or ReadWrite"
type = string
default = "ReadWrite"
}
variable "operating_system_disk_type" {
description = "Type of storage account to use with the OS disk - Options: Standard_LRS, StandardSSD_LRS or Premium_LRS"
type = string
default = "StandardSSD_LRS"
}
variable "ip_configuration_name" {
description = "ip configuration name"
type = string
default = ""
}
# Networking
variable "nic_id" {
type = list(string)
description = "ID of the nic"
}
variable "subnet_id" {
type = string
description = "ID of the subnet"
}
variable "private_ip_address_allocation" {
type = string
description = "Private ip allocation method"
}
variable "public_ip_allocation_method" {
type = string
description = "Public ip allocation method"
}
variable "public_ip_sku" {
description = "SKU to be used with this public IP - Basic or Standard"
type = string
default = "Standard"
}
modules/virtualmachine/outputs.tf
# Interface id
output "nic_id" {
description = "ids of the vm nics provisoned."
value = azurerm_network_interface.nic-linux.id
}
You get these errors, because these variables are marked as required. You can change that by giving them a default value:
# Plan Block Variables
variable "plan_name" {
description = "Plan Name"
type = string
default = ""
}
variable "plan_product" {
description = "Plan Product"
type = string
default = ""
}
variable "plan_publisher" {
description = "Plan Publisher"
type = string
default = ""
}
terraform version: v0.12.24
provider.azurerm v2.49.0
I am trying to build a vnet by having all the line items as variables and then populate them in
the variables.auto.tfvars file.
for my main.tf section:
resource "azurerm_virtual_network" "vnet" {
name = var.vnet_name
resource_group_name = var.rg_grp_name
address_space = var.vnet_cidr
location = var.region_location #match RG location
dns_servers = var.vnet_dns_servers
#tags stuff here
}
Resource "azurerm_subnet" "subnet" {
for_each = var.subnets
name = lookup(each.value, "name")
resource_group_name = var.rg_grp_name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = lookup(each.value, "cidr")
}
and in my variables.tf, which i am really unsure about;
###vnet section###################
#variable for defining what region
variable "name" {
type = string
}
#variable for defining what region
variable "resource_group_name" {
type = string
}
#variable for defining what region
variable "vnet_cidr" {
description = "address space"
type = list
}
#variable for defining what region
variable "region_location" {
type = string
}
#variable for defining what region
variable "vnet_dns_servers" {
type = list
}
#variable for defining what region
variable "subnets" {
type = map(object({
name = string
cidr = string
}))
}
##end subnet block
#variable for defining what region
variable "azregion" {
type = string
}
#####end vnet section#############
I dont have the variables.auto.tfvars section yet...
whats the best way to go about this?
Thanks
We can create the input variables by variable blocks but reference them as attributes on an object named var. We can access its value from within expressions as var.<NAME>, where <NAME> matches the label given in the declaration block.
So, according to the expressions in your main.tf file, the variable declaration block shoule be like this:
variable "vnet_name" {
description = "Name of the vnet to create"
type = string
# default = "acctvnet"
}
variable "rg_grp_name" {
description = "Name of the resource group to be imported."
type = string
# default = "testrg"
}
variable "vnet_cidr" {
type = list(string)
description = "The address space that is used by the virtual network."
# default = ["10.0.0.0/16"]
}
variable "region_location" {
type = string
# default = "eastus"
}
# If no values specified, this defaults to Azure DNS
variable "vnet_dns_servers" {
description = "The DNS servers to be used with vNet."
type = list(string)
# default = []
}
variable "subnets" {
type = map(object({
name = string
cidr = string
}))
# default = {
# subnet1 = {
# name = "subnet1"
# cidr = "10.0.1.0/24"
# },
# subnet2 = {
# name = "subnet2"
# cidr = "10.0.2.0/24"
# }
# }
}
If you would like to make terraform automatically load a number of variable definitions files, you can input the default values for that variable as the expression variable_name = default_value in the variables.auto.tfvarsfile .
vnet_name = "acctvnet"
rg_grp_name = "testrg"
vnet_cidr = ["10.0.0.0/16"]
region_location = "eastus"
vnet_dns_servers = []
subnets = {
subnet1 = {
name = "subnet1"
cidr = "10.0.1.0/24"
},
subnet2 = {
name = "subnet2"
cidr = "10.0.2.0/24"
}
}
You can check the source code in the vnet module with terraform for more details.
I'm trying to create varying number of VM's with different configurations. I'm setting for_each on the azurerm_windows_virtual_machine resource and looping through a map set in a tfvars file. The variable is set in the module but defined in the tfvars file.
I want to be able to create x amount of VM's with each one having a unique NIC attached. I am able to create the VM's but provisioning fails because the NIC is not unique. I have tried adding for_each using the same variable but I get the following errors:
Error: Incorrect attribute value type
on ../modules/compute/windows_vm/windows_vm.tf line 96, in resource "azurerm_network_interface_application_security_group_association" "application_security_group_association":
96: network_interface_id = [azurerm_network_interface.network_interface[each.key].id]
Inappropriate value for attribute "network_interface_id": string required.
Error: Incorrect attribute value type
on ../modules/compute/windows_vm/windows_vm.tf line 96, in resource "azurerm_network_interface_application_security_group_association" "application_security_group_association":
96: network_interface_id = [azurerm_network_interface.network_interface[each.key].id]
Inappropriate value for attribute "network_interface_id": string required.
This is my code:
# VM Network Interface
resource "azurerm_network_interface" "network_interface" {
for_each = var.servers
name = "nic-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}${each.value.name}"
resource_group_name = var.resource_group
location = var.location
enable_ip_forwarding = "false"
enable_accelerated_networking = "false"
ip_configuration {
name = "ipconfig1"
subnet_id = data.azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
primary = "true"
}
}
# Application Security Group
resource "azurerm_application_security_group" "application_security_group" {
name = "asg-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}"
resource_group_name = var.resource_group
location = var.location
}
resource "azurerm_network_interface_application_security_group_association" "application_security_group_association" {
for_each = var.servers
network_interface_id = [azurerm_network_interface.network_interface[each.key].id]
application_security_group_id = azurerm_application_security_group.application_security_group.id
}
resource "azurerm_network_interface_security_group_association" "network_security_group_association" {
for_each = var.servers
network_interface_id = [azurerm_network_interface.network_interface[each.key].id]
network_security_group_id = azurerm_network_security_group.network_security_group.id
}
# Azure Virtual Machine
resource "azurerm_windows_virtual_machine" "virtual_machine" {
for_each = var.servers
name = "vm-${var.environment}-${var.vm_identifier}${each.value.name}"
location = var.location
resource_group_name = var.resource_group
zone = each.value.zone
size = var.vm_size
network_interface_ids = [azurerm_network_interface.network_interface[each.key].id]
computer_name = "${var.vm_identifier}${each.value.name}"
admin_username = xxxx
admin_password = xxxx
provision_vm_agent = "true"
source_image_id = data.azurerm_shared_image.shared_image.id
boot_diagnostics {
storage_account_uri = data.azurerm_storage_account.diag_storage_account.primary_blob_endpoint
}
os_disk {
name = "vm-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}-os${each.value.name}"
caching = "ReadWrite"
storage_account_type = "Premium_LRS"
}
depends_on = [azurerm_network_interface.network_interface]
}
Variable within the root module that is used in the for_each and set in module variables.tf:
variable "servers" {
description = "Variable for defining each instance"
}
Variables in the module that map to each tfvars per environment:
variable "desktop_servers" {
description = "Variable for defining each instance"
}
variable "db_servers" {
description = "Variable for defining each instance"
}
The above are then defined in the tfvars as below:
desktop_servers = {
"Server_1" = {
name = 1,
zone = 1
}
"Server_2" = {
name = 2,
zone = 2
}
"Server_3" = {
name = 3,
zone = 3
}
}
db_servers = {
"Server_1" = {
name = 1,
zone = 1
}
}
You are assigning a list into network_interface_id, however it should be a string only.
Thus, instead of:
network_interface_id = [azurerm_network_interface.network_interface[each.key].id]
it should be
network_interface_id = azurerm_network_interface.network_interface[each.key].id
In its simplest form,
main.tf is as below:
data "azurerm_resource_group" "tf-rg-external" {
name = var.rg_name
}
# Reference existing Virtual Network
data "azurerm_virtual_network" "tf-vn" {
name = var.vnet_name
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
}
# Reference existing subnet
data "azurerm_subnet" "tf-sn" {
name = var.subnet_name
virtual_network_name = data.azurerm_virtual_network.tf-vn.name
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
}
resource "azurerm_network_security_group" "tf-nsg" {
name = var.app_nsg
location = data.azurerm_virtual_network.tf-vn.location
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
}
resource "azurerm_network_security_rule" "tf-nsr-5986" {
name = "Open Port 5986"
priority = 101
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "5986"
source_address_prefixes = var.allowed_source_ips
destination_address_prefix = "VirtualNetwork"
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
network_security_group_name = azurerm_network_security_group.tf-nsg.name
}
resource "azurerm_network_security_rule" "tf-nsr-3389" {
name = "Open Port 3389"
priority = 102
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefixes = var.allowed_source_ips
destination_address_prefix = "VirtualNetwork"
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
network_security_group_name = azurerm_network_security_group.tf-nsg.name
}
# Assosciate NSG to subnet
resource "azurerm_subnet_network_security_group_association" "tf-snnsg" {
subnet_id = data.azurerm_subnet.tf-sn.id
network_security_group_id = azurerm_network_security_group.tf-nsg.id
}
# Network inteface for Interface
resource "azurerm_network_interface" "tf-ni" {
count = var.vm_count
name = "${var.base_hostname}${format("%02d", count.index + 1)}-nic01"
location = data.azurerm_virtual_network.tf-vn.location
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
ip_configuration {
name = "${var.base_hostname}${format("%02d", count.index)}-iip01"
subnet_id = data.azurerm_subnet.tf-sn.id
private_ip_address_allocation = "dynamic"
public_ip_address_id = element(azurerm_public_ip.tf-pip.*.id, count.index)
}
}
resource "azurerm_public_ip" "tf-pip" {
count = var.vm_count
location = data.azurerm_virtual_network.tf-vn.location
name = "${var.base_hostname}${format("%02d", count.index + 1)}-pip01"
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
allocation_method = "Dynamic"
}
# Storage Account
resource "azurerm_storage_account" "tf-sa" {
count = var.vm_count
name = "${lower(var.base_hostname)}${format("%02d", count.index + 1)}${var.sto_acc_suffix}01"
location = data.azurerm_virtual_network.tf-vn.location
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
account_tier = var.sto_acc_tier_std
account_replication_type = var.sto_acc_rep_type_lrs
}
resource "azurerm_virtual_machine" "tf-vm" {
count = var.vm_count
name = "${var.base_hostname}${format("%02d", count.index + 1)}"
location = data.azurerm_virtual_network.tf-vn.location
resource_group_name = data.azurerm_resource_group.tf-rg-external.name
network_interface_ids = [element(azurerm_network_interface.tf-ni.*.id, count.index)]
vm_size = var.vm_size
delete_os_disk_on_termination = true
delete_data_disks_on_termination = true
storage_image_reference {
publisher = var.vm_publisher
offer = var.vm_offer
sku = var.vm_sku
version = var.vm_img_version
}
storage_os_disk {
name = "${var.base_hostname}${format("%02d", count.index + 1)}-wosdsk01"
caching = var.caching_option
create_option = var.create_option
managed_disk_type = var.managed_disk_std_lrs
}
os_profile {
computer_name = "${var.base_hostname}${format("%02d", count.index + 1)}"
admin_username = var.username
admin_password = var.password
}
os_profile_windows_config {
enable_automatic_upgrades = false
provision_vm_agent = "true"
}
}
variables.tf is below:
# Declare env variable
variable "rg_name" {
type = string
}
variable "vnet_name" {
type = string
}
variable "subnet_name" {
type = string
}
variable "app_nsg" {
type = string
}
variable "vm_count" {
type = number
}
variable "base_hostname" {
type = string
}
variable "sto_acc_suffix" {
type = string
}
variable "sto_acc_tier_std" {
type = string
default = "Standard"
}
variable "sto_acc_rep_type_lrs" {
type = string
default = "LRS"
}
variable "vm_size" {
type = string
}
variable "vm_publisher" {
type = string
}
variable "vm_offer" {
type = string
}
variable "vm_sku" {
type = string
}
variable "vm_img_version" {
type = string
}
variable "username" {
type = string
}
variable "password" {
type = string
}
variable "caching_option" {
type = string
default = "ReadWrite"
}
variable "create_option" {
type = string
default = "FromImage"
}
variable "managed_disk_std_lrs" {
type = string
default = "Standard_LRS"
}
variable "managed_disk_prem_lrs" {
type = string
default = "Premium_LRS"
}
variable "allowed_source_ips" {
description = "List of ips from which inbound connection to VMs is allowed"
type = list(string)
}
I run below command for upgrading terraform config to 0.12 and above
terraform 0.12upgrade
Error:
Error: Syntax error in configuration file
on main.tf line 22, in data "azurerm_resource_group" "tf-rg-external":
22: name = var.rg_name
Error while parsing: At 22:10: Unknown token: 22:10 IDENT var.rg_name
Error: Syntax error in configuration file
on variable.tf line 3, in variable "rg_name":
3: type = string
Error while parsing: At 3:10: Unknown token: 3:10 IDENT string
Any idea, what is the problem? this would work if I don't run terrafom 0.12upgrade command. It is intriguing me why it is not working. I did same upgrade command in another terraform config and I get similar error there.
One observation. This IDENT error comes for first variable in main.tf and variable.tf file. Unable to correlate this error.
You're already using 0.12 syntax, the 0.12upgrade command expects to find 0.11 syntax and will attempt to automatically update it.
e.g. name = var.rg_name - note the lack of ${}
See https://www.terraform.io/docs/commands/0.12upgrade.html
The terraform 0.12upgrade command applies several automatic upgrade rules to help prepare a module that was written for Terraform v0.11 to be used with Terraform v0.12.
(Emphasis mine)