For a project I use remote modules (git modules) these are called and executed in a terraformMain.tf file.
For example, I use an Azure Resource Group Module, this module is looped in the terraformMain.tf by "count = length (var.resourcegroups)". The problem I have now is that I want to use one of the two created Resource groups in the next module (creating VNET) but I keep encountering the following error:
Error: Unsupported attribute
on outputs.tf line 2, in output "RG": 2: value =
[module.resourceGroups.resource_group_name]
This value does not have any attributes.
Unsupported attribute
on terraformMain.tf line 33, in module "vnet": 33:
resourcegroup_name = module.resourceGroups.resource_group_name[0]
This value does not have any attributes.
The Azure Resource Group module code looks like this :
main.tf
resource "azurerm_resource_group" "RG" {
name = var.resource_group_name
location = var.location
}
variables.tf
variable "location" {
type = string
}
variable "resource_group_name" {
type = string
}
outputs.tf
output "resource_group_names" {
value = concat(azurerm_resource_group.RG.*.name, [""])[0]
}
The code of the terraformMain.tf looks like this:
terraformMain.tf
terraform {
required_version = ">= 0.13"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.45.1"
}
}
backend "azurerm" {
resource_group_name = "__terraformresourcegroup__"
storage_account_name = "__terraformstorageaccount__"
container_name = "__terraformcontainer__"
key = "__terraformkey__"
}
}
provider "azurerm" {
features {}
}
module "resourceGroups" {
count = length(var.resourcegroups)
source = "git::https://*****#dev.azure.com/****/TerraformAzureModules/_git/ResourceGroup"
location = var.location
resource_group_name = var.resourcegroups[count.index]
}
module "vnet" {
source = "git::https://*****#dev.azure.com/****/TerraformAzureModules/_git/VirtualNetwork"
resourcegroup_name = module.resourceGroups.resource_group_name[0]
location = var.location
vnet_name = var.vnet_name
count = length(var.subnet_names)
vnet_cidr = var.vnet_cidr[count.index]
subnet_cidr = var.subnet_cidr[count.index]
subnet_name = var.subnet_names[count.index]
}
variables.tf
variable "location" {
default = "westeurope"
}
variable "resourcegroups" {
default = ["rg1", "rg2"]
}
#Azure Vnet / Subnet
variable "vnet_name" {
default = "vnet_1"
}
variable "subnet_names" {
default = ["subnet1", "subnet2"]
}
variable "vnet_cidr" {
default = ["10.116.15.0/24"]
}
variable "subnet_cidr" {
default = ["10.116.15.0/26", "10.116.15.128/27"]
}
outputs.tf
output "RG" {
value = [module.resourceGroups.resource_group_name]
}
any help is appreciated!
Your resourceGroups module has count = length(var.resourcegroups) set, and so module.resourceGroups is a list of objects and therefore you will need to request a specific element from the list before accessing an attribute:
module.resourceGroups[0].resource_group_name
Or, if your goal was to return a list of all of the resource group names, you can use the [*] operator to concisely access the resource_group_name argument from each of the elements and return the result as a list:
resource.resourceGroups[*].resource_group_name
The variables in the module need to have a type or a default.
For example, this would be a valid file:
variable "location" {
type = string
}
variable "resource_group_name" {
type = string
}
The solution we have applied is to move the count from the terraformMain.tf to the resource module main.tf. this allowed us to pass the resoucgroups to the terraformMain through the output.tf of the module.
ResourceGroup module:
main.tf
resource "azurerm_resource_group" "RG" {
count = length(var.resource_group_name)
name = var.resource_group_name[count.index]
location = var.location
}
outputs.tf
output "resource_group_names" {
value = azurerm_resource_group.RG.*.name
}
terraformMain.tf code:
terraform {
required_version = ">= 0.13"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.45.1"
}
}
backend "azurerm" {
resource_group_name = "__terraformresourcegroup__"
storage_account_name = "__terraformstorageaccount__"
container_name = "__terraformcontainer__"
key = "__terraformkey__"
}
}
provider "azurerm" {
features {}
}
module "resourceGroups" {
source = "git::https://*****#dev.azure.com/*****/TerraformAzureModules/_git/ResourceGroup"
location = var.location
resource_group_name = var.resourcegroups
}
module "vnet" {
source = "git::https://******#dev.azure.com/*****/TerraformAzureModules/_git/VirtualNetwork"
resourcegroup_name = module.resourceGroups.resource_group_names[0]
location = var.location
vnet_name = var.vnet_name
vnet_cidr = var.vnet_cidr
subnet_cidr = var.subnet_cidr
subnet_name = var.subnet_names
}
I want to thank you for your contribution
Related
I'm just starting with terraform and I just don't grasp some of the basics.
I have two problems
I have a main.tf file where I initialise Terraform, declare 2 providers for Azure and Kubernetes, and define two modules.
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.2"
}
}
required_version = ">= 1.1.0"
}
provider "kubernetes" {
host = module.cluster.host
client_certificate = module.cluster.client_certificate
client_key = module.cluster.client_key
cluster_ca_certificate = module.cluster.cluster_ca_certificate
}
provider "azurerm" {
features {}
}
module "cluster" {
source = "./modules/cluster"
location = var.location
kubernetes_version = var.kubernetes_version
ssh_key = var.ssh_key
}
module "network" {
source = "./modules/network"
}
then in modules/cluster/cluster.tf I setup the resource group and the cluster.
when I define a new resource all azure and kubernetes providers modules are available.
I'm trying to add two new resources azurem_public_ip and an azurem_lb in modules/network/network.tf but the azurerm modules are not available to select
If I try and create those two resources in `modules/cluster/cluster.tf they are available
and I can write the so:
resource "azurerm_resource_group" "resource_group" {
name = var.resource_group_name
location = var.location
tags = {
Environment = "Production"
Team = "DevOps"
}
}
resource "azurerm_kubernetes_cluster" "server_cluster" {
...
}
resource "azurerm_public_ip" "public-ip" {
name = "PublicIPForLB"
location = azurerm_resource_group.resource_group.location
resource_group_name = azurerm_resource_group.resource_group.name
allocation_method = "Static"
}
resource "azurerm_lb" "load-balancer" {
name = "TestLoadBalancer"
location = azurerm_resource_group.resource_group.location
resource_group_name = azurerm_resource_group.resource_group.name
frontend_ip_configuration {
name = "PublicIPAddress"
public_ip_address_id = azurerm_public_ip.public-ip.id
}
}
Why aren't the providers available in network.tf?
Shouldn't they be available in the network module as they are in the cluster module?
From the docs network module should inherit the azurerm provider from main.tf
If not specified, the child >module inherits all of the >default (un-aliased) provider >configurations from the calling >module.
Many thanks for your help.
Tried to replicate the same scenario using below mentioned code. Everything is working as expected. Hope issue may cause because of module declaration.
Main tf code as follows:
provider "azurerm" {
features {}
}
provider "kubernetes" {
host = module.cluster.host
client_certificate = module.cluster.client_certificate
client_key = module.cluster.client_key
cluster_ca_certificate = module.cluster.cluster_ca_certificate
}
module "cluster" {
source = "./modules/cluster"
}
module "network" {
source = "./modules/network"
}
NOTE: No more parameters require on provider tf file. Just declaration of module is sufficient.
Provider tf file as follows:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.2"
}
}
required_version = ">= 1.1.0"
}
Cluster file as follows:
resource "azurerm_kubernetes_cluster" "example" {
name = "swarnaexample-aks1"
location = "East Us"
resource_group_name = "*********"
dns_prefix = "exampleaks1"
default_node_pool {
name = "default"
node_count = 1
vm_size = "Standard_D2_v2"
}
identity {
type = "SystemAssigned"
}
tags = {
Environment = "Production"
}
}
output "client_certificate" {
value = azurerm_kubernetes_cluster.example.kube_config.0.client_certificate
sensitive = true
}
output "kube_config" {
value = azurerm_kubernetes_cluster.example.kube_config_raw
sensitive = true
}
network tf file as follows:
resource "azurerm_resource_group" "example" {
name = "***********"
location = "East Us"
}
resource "azurerm_public_ip" "example" {
name = "swarnapIPForLB"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
allocation_method = "Static"
}
resource "azurerm_lb" "example" {
name = "swarnaLB"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
frontend_ip_configuration {
name = "PublicIPadd"
public_ip_address_id = azurerm_public_ip.example.id
}
}
from the code
Upon running of plan and apply
I am trying to pass output of StorageAccount and App Service Plan output values to Function App module. However I am not able to figure it out how to manage the variable.tf for root and child module
Here is my code in detailed to understand better
terraform.tfvars
#Resource Group
resourcegroupname = "eus-dev-test-rg"
asp-resourcegroupname = "eus-dev-shared-asp-rg"
location = "eastus"
#Storage Account
storageaccountname = "euspftestsa001"
#App Servicen Plan
serviceplanname = "eus-dev-shared-asp-01"
ostype = "Windows"
sku = "Y1"
#Function App
functionappname = "eus-dev-test-fnapp-02"
stack_version = { node = "~14" }
main.tf
module "ResourceGroup" {
source = "../../modules/ResourceGroup"
resourcegroupname = var.resourcegroupname
location = var.location
}
module "ASP-ResourceGroup" {
source = "../../modules/ResourceGroup"
resourcegroupname = var.asp-resourcegroupname
location = var.location
}
module "ApplicationServicePlan" {
source = "../../modules/ApplicationServicePlan"
resourcegroupname = module.ASP-ResourceGroup.rg_name_out
serviceplanname = var.serviceplanname
location = var.location
ostype = var.ostype
sku = var.sku
}
module "NODE_WA_StorageAccount" {
source = "../../modules/StorageAccount"
storageaccountname = var.storageaccountname
resourcegroupname = module.ResourceGroup.rg_name_out
location = var.location
}
module "FunctionApp" {
depends_on = [module.ResourceGroup, module.NODE_WA_StorageAccount, module.ApplicationServicePlan]
source = "../../modules/FunctionApp/test"
resourcegroupname = module.ResourceGroup.rg_name_out
location = var.location
service_plan_id = module.ApplicationServicePlan.app_sp_out
storageaccountname = module.NODE_WA_StorageAccount.sa_name_out
storage_account_access_key = module.NODE_WA_StorageAccount.sa_primary_access_key_out
functionappname = var.functionappname
stack_version = var.stack_version
}
variables.tf
variable "resourcegroupname" {
type = string
}
variable "asp-resourcegroupname" {
type = string
}
variable "location" {
type = string
}
variable "storageaccountname" {
type = string
}
variable "serviceplanname" {
type = string
}
variable "ostype" {
type = string
}
variable "sku" {
type = string
}
variable "stack_version" {
type = map
}
variable "functionappname" {
type = string
}
Modules code
Resource Group module
main.tf
resource "azurerm_resource_group" "rg" {
name = var.resourcegroupname
location = var.location
}
variable.tf
variable "resourcegroupname" {
type = string
}
variable "location" {
type = string
}
variable "tags" {
type = map(string)
}
output.tf
output "rg_name_out" {
value = azurerm_resource_group.rg.name
}
Storage Account module
main.tf
resource "azurerm_storage_account" "storageaccount" {
name = var.storageaccountname
resource_group_name = var.resourcegroupname
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
}
variable.tf
variable "resourcegroupname" {
type = string
description = "The name of the resource group"
}
variable "location" {
type = string
description = "resources should deploy only on 'eastus' as per the policy"
}
variable "storageaccountname" {
type = string
description = "The name of the Storage Account name"
}
output.tf
output "sa_primary_access_key_out"{
value = azurerm_storage_account.storageaccount.primary_access_key
}
output "sa_name_out"{
value = azurerm_storage_account.storageaccount.name
}
Azure Function App Module
main.tf
resource "azurerm_windows_function_app" "win-fn" {
name = var.functionappname
resource_group_name = var.resourcegroupname
location = var.location
storage_account_name = var.storageaccountname
storage_account_access_key = primaryaccesskey
service_plan_id = serviceplanid
site_config {
ftps_state = "FtpsOnly"
application_stack {
node_version = lookup(var.stack_version, "node", null)
java_version = lookup(var.stack_version, "java", null)
}
}
}
variable.tf
variable "resourcegroupname" {
type = string
description = "The name of the resource group"
}
variable "location" {
type = string
description = "resources should deploy only on 'eastus' as per the policy"
}
variable "functionappname" {
type = string
}
variable "storageaccountname"{
type = string
description = "The name of the WebApp SKU"
}
variable "stack_version" {
type = map
}
ERROR while executing the terraform plan
╷
│ Error: Unsupported argument
│
│ on main.tf line 55, in module "FunctionApp":
│ 55: service_plan_id = module.ApplicationServicePlan.app_sp_out
│
│ An argument named "service_plan_id" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│ on main.tf line 59, in module "FunctionApp":
│ 59: storage_account_access_key = module.NODE_WA_StorageAccount.sa_primary_access_key_out
│
│ An argument named "storage_account_access_key" is not expected here.
You have to define additional two variables in the FunctionApp module. The root module does not automatically map the values of the variables to the arguments in the child module. In other words, arguments storage_account_access_key and service_plan_id are unknown to the root module. To fix this, you just need to define the two variables in the FunctionApp variables.tf:
variable "service_plan_id" {
type = string
description = "Service Plan ID."
}
variable "storage_account_access_key" {
type = string
description = "Storage account access key."
}
Then, in the child module FunctionApp, change this:
resource "azurerm_windows_function_app" "win-fn" {
name = var.functionappname
resource_group_name = var.resourcegroupname
location = var.location
storage_account_name = var.storageaccountname
storage_account_access_key = var.storage_account_access_key # <--- reference to the new variable
service_plan_id = var.service_plan_id # <--- reference to the new variable
site_config {
ftps_state = "FtpsOnly"
application_stack {
node_version = lookup(var.stack_version, "node", null)
java_version = lookup(var.stack_version, "java", null)
}
}
}
Think of module variables as inputs to functions in programming languages. If you try to pass the value to an undefined variable that will not work. The same logic applies here. Any input you want to provide to a module you have to define. Then, that input must have a value. You can either set it to a default one when defining the variable or leave it undefined and provide it when calling the 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
}
main.tf wrote:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.26"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
name = "Product-RG"
location = var.location
}
resource "azurerm_virtual_network" "vnet" {
resource_group_name = azurerm_resource_group.rg.name
name = "Product-VNet"
address_space = [lookup(var.vnetAddress, var.location)]
location = var.location
subnet {
name = "Web-Sub1"
address_prefix = ["${lookup(var.subnetAddress[var.location], "web1")}"]
}
subnet {
name = "Web-Sub2"
address_prefix = [lookup(var.subnetAddress[var.location], "web2")]
}
In Web-Sub1, i originally brought address_prefix like Web-Sub2, but now i'm trying like address_prefix on Web-Sub1 after the error occurred.
An error has occurred as below.
Error: Incorrect attribute value type
on main.tf line 27, in resource "azurerm_virtual_network" "vnet":
27: address_prefix = ["${lookup(var.subnetAddress[var.location], "web1")}"]
Inappropriate value for attribute "address_prefix": string required.
Error: Incorrect attribute value type
on main.tf line 31, in resource "azurerm_virtual_network" "vnet":
31: address_prefix = [lookup(var.subnetAddress[var.location], "web2")]
Inappropriate value for attribute "address_prefix": string required.
variable.tf wrote:
variable "location" {}
variable "vnetAddress" {
type = map
default = {
westus = "192.168.1.0/27"
eastus = "192.168.11.0/27"
}
}
variable "subnetAddress" {
type = map
default = {
westus = {
web1 = "192.168.1.0/27"
web2 = "192.168.1.32/27"
was1 = "192.168.1.64/27"
was2 = "192.168.1.96/27"
db1 = "192.168.1.128/27"
db2 = "192.168.1.160/27"
}
eastus = {
web1 = "192.168.11.0/27"
web2 = "192.168.11.32/27"
was1 = "192.168.11.64/27"
was2 = "192.168.11.96/27"
db1 = "192.168.11.128/27"
db2 = "192.168.11.160/27"
}
}
}
I wonder why there is an error that needs to be written in string format and why I can't bring the data.
You are almost there, just that address_prefix argument needs to be a string and you are passing a list of strings address_prefix = [lookup(var.subnetAddress[var.location], "web2")]
subnet {
name = "Web-Sub1"
address_prefix = lookup(var.subnetAddress[var.location], "web1")
}
subnet {
name = "Web-Sub2"
address_prefix = lookup(var.subnetAddress[var.location], "web2")
}
This should work.
Refer azurerm_virtual_network resource, address_prefix is passed as a string rather a list of strings.
Also for public ip id getting: "
Error: Can not parse "ip_configuration.0.public_ip_address_id" as a
resource id: Cannot parse Azure ID: parse
module.resource.azurerm_public_ip.primary.id: invalid URI for request
"
As the network is a nested module for the resource module, will you please suggest, where I'm missing?
main.tf file:
#Select provider
provider "azurerm" {
subscription_id = "xxxxxxxxxxxxxxxxxxxxxx"
version = "~> 2.2"
features {}
}
module "resource" {
source = "./modules/resource"
resource_group_name = "DevOpsPoc-primary"
location = "southeastasia"
}
module "network" {
source = "./modules/network"
virtual_network = "primaryvnet"
subnet = "primarysubnet"
address_space = "192.168.0.0/16"
address_prefix = "192.168.1.0/24"
public_ip = "backendvmpip"
location = "southeastasia"
primary_nic = "backendvmnic"
#vnet_subnet_id = element(module.network.vnet_subnets, 0)
primary_ip_conf = "backendvm"
}
resource module main.tf file:
resource "azurerm_resource_group" "primary" {
name = "var.resource_group_name"
location = "var.location"
tags = {
environment = "env"
}
}
network module main.tf file:
#Create Virtual Network in Primary Resource Group
resource "azurerm_virtual_network" "primary" {
name = "var.virtual_network"
resource_group_name = "module.resource.azurerm_resource_group.primary.name"
address_space = ["var.address_space"]
location = "module.resource.azurerm_resource_group.primary.location"
tags = {
environment = "env"
}
}
#Create Subnet in Virtual Network
resource "azurerm_subnet" "primary" {
name = "var.subnet"
resource_group_name = "module.resource.azurerm_resource_group.primary.name"
virtual_network_name = "module.resource.azurerm_virtual_network.primary.name"
address_prefix = "var.address_prefix"
# tags = {
# environment = "env"
# }
}
output "subnet_id"{
value = "module.resource.azurerm_subnet.primary.id"
}
#Create public IP address
resource "azurerm_public_ip" "primary" {
name = "var.public_ip"
location = "module.resource.azurerm_resource_group.primary.location"
resource_group_name = "module.resource.azurerm_resource_group.primary.name"
allocation_method = "Dynamic"
tags = {
environment = "env"
}
}
output "public_ip_id"{
value = "module.resource.azurerm_public_ip.id"
}
#Create Network Interface
resource "azurerm_network_interface" "primary" {
name = "var.primary_nic"
location = "module.resource.azurerm_resource_group.primary.location"
resource_group_name = "module.resource.azurerm_resource_group.primary.name"
ip_configuration {
name = "var.primary_ip_conf"
subnet_id = "module.resource.azurerm_subnet.primary.id"
private_ip_address_allocation = "Dynamic"
public_ip_address_id = "module.resource.azurerm_public_ip.primary.id"
}
tags = {
environment = "env"
}
}
There are some places need to be corrected in your codes:
You don't need double quotes"" in variables or expression refers to Interpolation Syntax. For example "var.virtual_network" should be var.virtual_network.
You can directly reference resources in the same main.tf file instead of from the module block. For example, change virtual_network_name = "module.resource.azurerm_virtual_network.primary.name" to virtual_network_name = azurerm_virtual_network.primary.name in the resource "azurerm_subnet" block.
The syntax for referencing module outputs is ${module.NAME.OUTPUT}, where NAME is the module name given in the header of the module configuration block and OUTPUT is the name of the output to reference. You can declare resource group name and location in module "network" instead of using it from the ./modules/network/main.tf file.
Here is the working code and you could get more references in this document:
main.tf file in the root directory
module "resource" {
source = "./modules/resource"
resource_group_name = "DevOpsPoc-primary"
location = "southeastasia"
}
module "network" {
source = "./modules/network"
resource_group_name = module.resource.RGname
location = module.resource.location
virtual_network = "primaryvnet"
subnet = "primarysubnet"
address_space = ["192.168.0.0/16"]
address_prefix = "192.168.1.0/24"
public_ip = "backendvmpip"
primary_nic = "backendvmnic"
#vnet_subnet_id = element(module.network.vnet_subnets, 0)
primary_ip_conf = "backendvm"
}
main.tf in the directory ./modules/resource
variable "resource_group_name" {}
variable "location" {}
resource "azurerm_resource_group" "primary" {
name = var.resource_group_name
location = var.location
}
output "RGname" {
value = "${azurerm_resource_group.primary.name}"
}
output "location" {
value = "${azurerm_resource_group.primary.location}"
}
main.tf in the directory ./modules/network and also declare the variables in the same directory.
#Create Virtual Network in Primary Resource Group
resource "azurerm_virtual_network" "primary" {
name = var.virtual_network
resource_group_name = var.resource_group_name
address_space = var.address_space
location = var.location
}
#Create Subnet in Virtual Network
resource "azurerm_subnet" "primary" {
name = var.subnet
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.primary.name
address_prefix = var.address_prefix
}
output "subnet_id"{
value = azurerm_subnet.primary.id
}
#Create public IP address
resource "azurerm_public_ip" "primary" {
name = var.public_ip
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Dynamic"
}
output "public_ip_id"{
value = azurerm_public_ip.primary.id
}
#Create Network Interface
resource "azurerm_network_interface" "primary" {
name = var.primary_nic
location = var.location
resource_group_name = var.resource_group_name
ip_configuration {
name = var.primary_ip_conf
subnet_id = azurerm_subnet.primary.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.primary.id
}
}
I had a similar error when setting up an Azure App Service using Terraform.
module.app_service.azurerm_app_service.app_service: Creating...
│ Error: Cannot parse Azure ID: parse "27220": invalid URI for request
│
│ with module.app_service.azurerm_app_service.app_service,
│ on ../../../modules/azure/app-service/main.tf line 1, in resource "azurerm_app_service" "app_service":
│ 1: resource "azurerm_app_service" "app_service" {
Here's how I fixed it:
The issue was that I used the wrong value for the App Service Plan ID in my module.
I was using 27220 as the App Service Plan ID, instead of the actual value of the App Service Plan ID which of this format:
"/subscriptions/fec545cd-bead-43ba-84c6-5738cdc7e458/resourceGroups/MyDevRG/providers/Microsoft.Web/serverfarms/MyDevLinuxASP"
That's all