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.
Related
I am new to terraform and I am trying to create module for multiple vnets and under that multiple subnets
I am able to create multiple vnets using the module but I am facing issue in creating multiple subnets on one or more of the vnets created.
Below is my code for the module and as well as main.tf
network resources module/main.tf
data "azurerm_resource_group" "network" {
name = var.resource_group_name
}
resource "azurerm_virtual_network" "vnets" {
count = length(var.vnet_names)
name = var.vnet_names[count.index]
resource_group_name = data.azurerm_resource_group.network.name
location = var.vnet_location != null ? var.vnet_location : data.azurerm_resource_group.network.location
address_space = [var.vnet_adress_spaces[count.index]]
}
network resources module/variables.tf
variable "vnet_names" {
description = "Name of the vnets to be created"
type = list(string)
default = ["vnet1","vnet2","vnet3"]
}
variable "vnet_adress_spaces" {
description = "Name of the vnets to be created"
type = list(string)
default = ["192.168.0.0/16" ,"10.0.0.0/16","10.80.0.0/16"]
}
variable "resource_group_name" {
description = "Name of the resource group to be imported."
type = string
}
variable "vnet_location" {
description = "The location of the vnet to create. Defaults to the location of the resource group."
type = string
default = null
}
variable "subnet_names" {
description = "The list of subnets which needs to be created"
type = list(list(string))
default = [[],["subnet1_vnet1","subnet2_vnet1"],["subnet1_vnet3","subnet2_vnet3","subnet3_vnet3"]]
}
variable "subnet_addresses" {
description = "The list of subnets which needs to be created"
type = list(list(string))
default = [[],["10.0.2.0/24","10.0.0.0/24"],["10.80.2.0/24","10.80.1.0/24","10.80.0.0/24"]]
}
main.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.98.0"
}
}
}
# Configure the Microsoft Azure Provider
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg1" {
name = "rg1"
location = "West Europe"
}
module network {
source = "./network_resources"
resource_group_name = azurerm_resource_group.rg1.name
}
3 vnets are successfully created but I am facing issue in writing subnet creation as mentioned in variables.tf
Please can you help me with that or suggest a better way of implementing this
Output.tf of module
output "vnet_names" {
description = "The name of the virtual networks"
value = {for k, v in azurerm_virtual_network.vnets: k => v.name}
}
output "vnet_addresses" {
description = "The name of the virtual networks"
value = {for k, v in azurerm_virtual_network.vnets: k => v.address_space}
}
output "subnet_names" {
description = "The name of the subnets"
value = {for k, v in azurerm_subnet.subnets: k => v.name}
}
output "subnet_addresses" {
description = "The name of the subnet addresses"
value = {for k, v in azurerm_subnet.subnets: k => v.address_prefixes}
}
output "subnet_ids" {
description = "The name of the subnet addresses"
value = {for k, v in azurerm_subnet.subnets: k => v.id}
}
When I am taking the subnet value same for two vnets as per the updated variables.tf
vnets = {
"mel-dev-identity-vnet01" = {
address_space = "10.0.0.0/16",
subnets = [
{
subnet_name = "subnet-mel-AD-dev"
subnet_address = "10.0.2.0/24"
service_endpoints = []
},
{
subnet_name = "subnet-mel-okt-dev"
subnet_address = "10.0.0.0/24"
service_endpoints = []
},
{
subnet_name = "GatewaySubnet"
subnet_address = "10.0.0.0/26"
service_endpoints = []
},
]
},
"mel-dev-identity-vnet02" = {
address_space = "10.80.0.0/16"
subnets = [
{
subnet_name = "subnet-syd-AD-dev"
subnet_address = "10.80.2.0/24"
service_endpoints = []
},
{
subnet_name = "subnet-syd-okt-dev"
subnet_address = "10.80.1.0/24"
service_endpoints = []
},
{
subnet_name = "GatewaySubnet"
subnet_address = "10.80.0.0/26"
service_endpoints = []
},
]
}
}
I am getting the below error:
│ Error: Duplicate object key
│
│ on network_resources\locals.tf line 11, in locals:
│ 11: subnets = { for subnet in local.subnets_flatlist : subnet.subnet_name => subnet }
│ ├────────────────
│ │ subnet.subnet_name is "GatewaySubnet"
│
│ Two different items produced the key "GatewaySubnet" in this 'for' expression. If duplicates are expected, use the
│ ellipsis (...) after the value expression to enable grouping by key.
I see two issues in your code:
You store attributes (e.g. subnet_name, subnet_addressed) of the same resources in different variables of type list or nested list.
This way you have to ensure consistency across the different variables manually which can become tedious and error prone. Imagine you want to add a third subnet to vnet bupavnet2. You have to make sure that you insert the new name and subnet at the corresponding positions in two nested lists.
BTW: Is it intended that the subnets in vnet bupavnet2 are named subnet#-bupavnet1 ? See what I mean ??? :)
In order to create multiple subnets in multiple vnets dynamically, you would need a nested loop which iterates over the vnets in the outer loop and across the subnets in the inner loop. Terraform, however, does not support nested for_each loops on resource level.
One way to overcome the first issue is to use complex types like objects or maps in order to make the relationship between the attributes of a resource explicit. This way it would be easy to spot the naming issue of the subnets in bupavnet2. If you want to add an additional subnet, you just need to add an additional object to the subnets list.
variable "vnets" {
type = map(object({
address_space = string
subnets = list(object({
subnet_name = string
subnet_address = string
}))
}))
default = {
"bupavnet1" = {
address_space = "192.168.0.0/16",
subnets = []
},
"bupavnet2" = {
address_space = "10.0.0.0/16",
subnets = [
{
subnet_name = "subnet1_bupavnet1"
subnet_address = "10.0.2.0/24"
},
{
subnet_name = "subnet2_bupavnet1"
subnet_address = "10.0.0.0/24"
}
]
},
"bupavnet3" = {
address_space = "10.80.0.0/16"
subnets = [
{
subnet_name = "subnet1_bupavnet3"
subnet_address = "10.80.2.0/24"
},
{
subnet_name = "subnet2_bupavnet3"
subnet_address = "10.80.1.0/24"
},
{
subnet_name = "subnet3_bupavnet3"
subnet_address = "10.80.0.0/24"
},
]
}
}
}
In succession, the creation of the vnets would change to
resource "azurerm_virtual_network" "vnets" {
for_each = var.vnets
name = each.key
resource_group_name = data.azurerm_resource_group.network.name
location = var.vnet_location != null ? var.vnet_location : data.azurerm_resource_group.network.location
address_space = [each.value.address_space]
}
Now let's have a look how to tackle the nested for loop issue. In Terraform you would address this by flattening the nested structure which we defined above. In the first step we create a flat list of objects representing the subnets to be created. So our variable subnets_flatlist has the type tuple of objects.
Unfortunately the for_each argument in Terraform requires the type map or set of strings. So we need a second step to create a map out of our flat list.
locals {
subnets_flatlist = flatten([for key, val in var.vnets : [
for subnet in val.subnets : {
vnet_name = key
subnet_name = subnet.subnet_name
subnet_address = subnet.subnet_address
}
]
])
subnets = { for subnet in local.subnets_flatlist : subnet.subnet_name => subnet }
}
Once we created our helper structures we can iterate over the subnets map and create the subnet resources:
resource "azurerm_subnet" "subnets" {
for_each = local.subnets
name = each.value.subnet_name
resource_group_name = data.azurerm_resource_group.network.name
virtual_network_name = azurerm_virtual_network.vnets[each.value.vnet_name].name
address_prefixes = [each.value.subnet_address]
}
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'm completely new to terraform and I'm trying to learn and write a TF code to automate Azure VM deployment. I'm trying to cover each parts as modules (except rg) rather than keeping it in a single main.tf file.
My intention is to create 1 vnet (TESTVNET) and create multiple subnets in same Vnet, where I can define the subnet name and address in my tfvars file.
I'm able to reach till creation on VNet, but cant loop through the defined subnets
Please go through my code. File Main.tf
resource "azurerm_resource_group" "resource_group" {
name = var.RGname
location = var.RGlocation
}
module "VNET" {
source = "./Modules/NetworkConfig"
name = var.VNETname
address_space = var.address_space
location = var.RGlocation
resource_group_name = azurerm_resource_group.resource_group.name
}
module "SUBNETS" {
source = "./Modules/SubnetConfig"
Subnetlist = var.Subnetlist
virtual_network_name = module.VNET.vnet_name
resource_group_name = azurerm_resource_group.resource_group.name
depends_on = [azurerm_resource_group.resource_group, module.VNET.vnet]
}
Variables.tf (of main)
variable "RGlocation" {
}
variable "RGname" {
}
variable "VNETname" {
}
variable "address_space" {
}
variable "Subnetlist" {
type = map(object({
name = list(string)
address = list(string)
}))
}
File main.tfvars
RGlocation = "westus"
RGname = "TEST-RG1"
VNETname = "TEST-VNET-01"
address_space = "10.0.0.0/16"
Subnetlist = {
"list" = {
name = ["TESTSUBNET","TESTSUBNET1","TESTSUBNET2"]
address = ["10.0.1.0/24","10.0.2.0/24","10.0.3.0/24"]
}
}
File Subnets.tf (module)
resource "azurerm_subnet" "SUBNETS" {
for_each=var.Subnetlist
name=each.value.name
address_prefixes=each.value.address
resource_group_name = var.resource_group_name
virtual_network_name = var.virtual_network_name
}
File variable.tf (subnet module)
variable "resource_group_name" {
}
variable "virtual_network_name" {
}
variable "Subnetlist" {
type = map(object({
name = list(string)
address = list(string)
}))
}
Below if the error that I'm getting
╷
│ Error: Incorrect attribute value type
│
│ on Modules\SubnetConfig\Subnet.tf line 3, in resource "azurerm_subnet" "SUBNETS":
│ 3: name=each.value.name
│ ├────────────────
│ │ each.value.name is list of string with 3 elements
│
│ Inappropriate value for attribute "name": string required.
Could anyone please tell me how to resolve it? Also, please do let me know if this is not the right approach.
The way you iterate over Subnetlist is incorrect - you only get the value of "list" key, ending up with a bundle of subnets instead of individual items. Make it a map of individual subnet objects instead:
variable "Subnetlist" {
type = map(object({
name = string
address = string
}))
}
Then pass it in tfvars like:
Subnetlist = {
"s1" = { name = "TESTSUBNET", address = "10.0.1.0/24" },
"s2" = { name = "TESTSUBNET1", address = "10.0.2.0/24" },
"s3" = { name = "TESTSUBNET2", address = "10.0.3.0/24" }
}
Finally consume it in the module like this:
resource "azurerm_subnet" "SUBNETS" {
for_each = var.Subnetlist
name = each.value.name
address_prefixes = each.value.address
resource_group_name = var.resource_group_name
virtual_network_name = var.virtual_network_name
}
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
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
}