Unable to peer Vnet in Azure using Terraform - azure

i'hv list of Vnet in azure and through count trying to peer from index[0] to rest all of vNet in list. Not sure how to put logic for rest vNet that count must start from index[1] instead [0].
While mentioning index.count , it is trying to peer with same vNet at last and throwing error.
Here is my code.
Variable.tf
===========
variable "rg" {
type= list(string)
description = " Name of Resource Group"
default = ["hub", "ansible", "spoke1", "spoke2", "spoke3", "spoke4", "spoke5"]
}
#------------------------------:Vnet's:--------------------------------------------
variable "vnet_name" {
description = "Vnet Details "
type = list(string)
default = ["hub_vnet", "ansible_vnet", "spoke1_vnet", "spoke2_vnet", "spoke3_vnet", "spoke4_vnet", "spoke5_vnet"]
}
Main.tf
========
resource "azurerm_virtual_network_peering" "az_to_rest" {
name = element(var.vnet_name, count.index)
resource_group_name = azurerm_resource_group.az_rg[0].name
virtual_network_name = azurerm_virtual_network.az_vnet[0].name
remote_virtual_network_id = azurerm_virtual_network.az_vnet[count.index].id
count = length(var.vnet_name)
}

I tested it for 3 vnets in 3 resource groups using the below code:
variable "rg" {
type= list(string)
description = " Name of Resource Group"
default = ["testgroup","hubtest","ansibletest"]
}
#------------------------------:Vnet's:--------------------------------------------
variable "vnet_name" {
description = "Vnet Details "
type = list(string)
default = ["ansuman_vnet","hub_vnet","ansible_vnet"]
}
provider "azurerm" {
features {}
}
data "azurerm_resource_group" "test" {
count = length(var.rg)
name = element(var.rg,count.index)
}
data "azurerm_virtual_network" "vnet" {
count = length(var.rg)
name = element(var.vnet_name, count.index)
resource_group_name = element(data.azurerm_resource_group.test.*.name, count.index)
}
resource "azurerm_virtual_network_peering" "az_to_rest" {
name = element(var.vnet_name, count.index)
resource_group_name = "${data.azurerm_resource_group.test.0.name}"
virtual_network_name = "${data.azurerm_virtual_network.vnet.0.name}"
remote_virtual_network_id = data.azurerm_virtual_network.vnet[count.index].id
count = length(var.vnet_name)
}
output:
As you can see from the above image, it errors out as its trying to peer with itself as well.
So , as a solution I have hard coded the virtual network name and resource group that I want to peer with other vnets and removed it from the list like below:
variable "rg" {
type= list(string)
description = " Name of Resource Group"
default = ["hubtest","ansibletest"]
}
#------------------------------:Vnet's:--------------------------------------------
variable "vnet_name" {
description = "Vnet Details "
type = list(string)
default = ["hub_vnet","ansible_vnet"]
}
provider "azurerm" {
features {}
}
data "azurerm_resource_group" "test" {
count = length(var.rg)
name = element(var.rg,count.index)
}
data "azurerm_virtual_network" "vnet" {
count = length(var.rg)
name = element(var.vnet_name, count.index)
resource_group_name = element(data.azurerm_resource_group.test.*.name, count.index)
}
resource "azurerm_virtual_network_peering" "az_to_rest" {
name = element(var.vnet_name, count.index)
resource_group_name = "testgroup" # resource group of vnet1
virtual_network_name = "ansuman_vnet"#vnet1
remote_virtual_network_id = data.azurerm_virtual_network.vnet[count.index].id
count = length(var.vnet_name)
}
Output:

Related

get the subnetid from subnets of type map(object)

I need to fetch the subnetid from azurerm_subnet data resource as subnet is used in dynamic block of azurerm_virtual_network as map(object) type
resource "azurerm_virtual_network" "example" {
name = "example-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
dynamic "subnet" {
for_each = var.subnets
content {
name = subnet.value.name
address_prefix = subnet.value.address_prefix
security_group = azurerm_network_security_group.example[subnet.key].id
}
}
}
Fetch the second subnetid to attach it to storage account
resource "azurerm_storage_account" "example" {
count = length(var.subnets)
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
network_rules {
default_action = "Deny"
virtual_network_subnet_ids = ["${data.azurerm_subnet.subnetid.id}"]
}
}
Please can any one help to solve as i want to declare subnet in azurerm_virtual_network as dynamic block and get the subnet if from the data resource and please find my terraform.tfvars as below
subnets = {
subnet1 = {
name = "subnet1"
address_prefix = "10.0.0.0/24"
}
subnet2 = {
name = "subnet2"
address_prefix = "10.0.1.0/24"
}
subnet3 = {
name = "subnet3"
address_prefix = "10.0.2.0/24"
}
}
IMPORTANT
count = length(var.subnets) in resource "azurerm_storage_account" "example" {} is still there in your question which is logically incorrect as I have stated in the comments.
Answer
With your comments, I am assuming that you want to use id of subnet2 in network_rules of resource "azurerm_storage_account" "example" {}. With your current approach where creating subnets within the virtual network resource you have to use splat expressions and locals to make a map out of the set object and then can directly refer wherever is required.
While doing referencing even with locals and splat expressions it is still required to use the name of the subnet as it is not possible for terraform to know what you want without any data.
resource "azurerm_virtual_network" "example" {
name = "example-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
dynamic "subnet" {
for_each = var.subnets
content {
name = subnet.value.name
address_prefix = subnet.value.address_prefix
# security_group = azurerm_network_security_group.example[subnet.key].id ## I have ignored it as no relevant code is shared###
}
}
}
locals {
subnets = { for subnet in azurerm_virtual_network.example.subnet : subnet.name => subnet }
}
resource "azurerm_storage_account" "example" {
#count = length(var.subnets) ## Removed it too as logically incorrect with the current code ##
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
network_rules {
default_action = "Deny"
virtual_network_subnet_ids = [local.subnets.subnet2.id]
}
You do not need a data source when referencing the attributes from one resource/module to another resource/module in the root module.
However, I suggest using azurerm_subnet resource for easier reference in spite of creating subnets in the virtual network resource itself because your might need Microsoft.Storage service_endpoints in your subnets for working with storage account with network_rules.

Azure Terraform Virtual Vetwork Peering Error (peering two existing vnets)

Goal:
to create a terraform module that will peer two existing vnet's across regions.
Issue: when I do terraform apply I receive this output error:
Error Output:
Error: network.VirtualNetworkPeeringsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="PeeringRemoteVnetIsSameAsParentVnet" Message="RemoteNetwork property of the peering /subscriptions/[REDACTED]/ cannot reference parent virtual network of the peering." Details=[]
on main.tf line 12, in resource "azurerm_virtual_network_peering" "source-to-destination":
12: resource "azurerm_virtual_network_peering" "source-to-destination" {
Error Output:
network.VirtualNetworkPeeringsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="PeeringRemoteVnetIsSameAsParentVnet" Message="RemoteNetwork property of the peering /subscriptions/[REDACTED]/ cannot reference parent virtual network of the peering." Details=[]
on main.tf line 25, in resource "azurerm_virtual_network_peering" "destination-to-source":
25: resource "azurerm_virtual_network_peering" "destination-to-source" {
Idea:
the idea is to create a terraform module so when other members of our team need to peer two existing vnet's they can pass in the terraform.tfvars file and deploy a vnet peering.
Research:
Below are the documentation references I have been following:
https://www.terraform.io/docs/providers/azurerm/r/virtual_network_peering.html
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network_peering
Have not discovered examples of peering two existing vnets.
//see code below
my main.tf file
##
# This will Peer two existing VNets across regions
##
provider "azurerm" {
version = ">=2.0.0"
features {}
subscription_id = var.subscription_id
}
# initiates source to destination peering between to existing vnets
resource "azurerm_virtual_network_peering" "source-to-destination" {
name = "peering-to-${var.destination_peer.virtual_network_name}"
resource_group_name = data.azurerm_virtual_network.existing_source_vnet.resource_group_name
virtual_network_name = data.azurerm_virtual_network.existing_source_vnet.name
remote_virtual_network_id = data.azurerm_virtual_network.existing_source_vnet.id
allow_virtual_network_access = var.allow_virtual_network_access
allow_forwarded_traffic = var.allow_forwarded_traffic
allow_gateway_transit = var.allow_gateway_transit
use_remote_gateways = var.use_remote_gateways
depends_on = [data.azurerm_virtual_network.existing_source_vnet]
}
# initiates destination to source peering between to existing vnets
resource "azurerm_virtual_network_peering" "destination-to-source" {
name = "peering-from-${var.source_peer.virtual_network_name}"
resource_group_name = data.azurerm_virtual_network.existing_destination_vnet.resource_group_name
virtual_network_name = data.azurerm_virtual_network.existing_destination_vnet.name
remote_virtual_network_id = data.azurerm_virtual_network.existing_destination_vnet.id
allow_virtual_network_access = var.allow_virtual_network_access
allow_forwarded_traffic = var.allow_forwarded_traffic
allow_gateway_transit = var.allow_gateway_transit
use_remote_gateways = var.use_remote_gateways
depends_on = [data.azurerm_virtual_network.existing_destination_vnet]
}
my data.tf file
##
# Existing Vnet Data
##
data "azurerm_virtual_network" "existing_source_vnet" {
resource_group_name = lookup(var.source_peer, "resource_group_name")
name = lookup(var.source_peer, "virtual_network_name")
}
data "azurerm_subnet" "src_subnet" {
name = lookup(var.source_peer, "name")
virtual_network_name = lookup(var.source_peer, "virtual_network_name")
resource_group_name = lookup(var.source_peer, "resource_group_name")
}
data "azurerm_virtual_network" "existing_destination_vnet" {
resource_group_name = lookup(var.destination_peer, "resource_group_name")
name = lookup(var.destination_peer, "virtual_network_name")
}
data "azurerm_subnet" "dtn_subnet" {
name = lookup(var.destination_peer, "name")
virtual_network_name = lookup(var.destination_peer, "virtual_network_name")
resource_group_name = lookup(var.destination_peer, "resource_group_name")
}
my variables.tf file
# This will Peer two existing VNets across regions
##
# Account Inputs
##
variable "subscription_id" {
type = string
}
##
# Input
##
variable "allow_gateway_transit" {
type = string
default = false
}
variable "use_remote_gateways" {
type = string
default = false
}
variable "allow_forwarded_traffic" {
type = string
default = false
}
variable "allow_virtual_network_access" {
type = string
default = true
}
variable "source_peer" {
type = object({
resource_group_name = string
virtual_network_name = string
remote_virtual_network_id = string
name = string
})
}
variable "destination_peer" {
type = object({
resource_group_name = string
virtual_network_name = string
remote_virtual_network_id = string
name = string
})
}
my output.tf file
##
# Output Of Virtual Network ID
##
output "virtual_network_id_src" {
value = data.azurerm_virtual_network.existing_source_vnet.id
}
output "subnet_id_src" {
value = data.azurerm_subnet.src_subnet.id
}
output "virtual_network_id_dtn" {
value = data.azurerm_virtual_network.existing_destination_vnet.id
}
output "subnet_id_dtn" {
value = data.azurerm_subnet.dtn_subnet.id
}
For the error message, it means that you have set remote_virtual_network_id = data.azurerm_virtual_network.existing_source_vnet.id as the VNet itself instead the remote VNet. You should set the remote VNet like this remote_virtual_network_id = data.azurerm_virtual_network.existing_destination_vnet.id
# initiates source to destination peering between to existing vnets
resource "azurerm_virtual_network_peering" "source-to-destination" {
name = "peering-to-${var.destination_peer.virtual_network_name}"
resource_group_name = data.azurerm_virtual_network.existing_source_vnet.resource_group_name
virtual_network_name = data.azurerm_virtual_network.existing_source_vnet.name
remote_virtual_network_id = data.azurerm_virtual_network.existing_destination_vnet.id #change here
allow_virtual_network_access = var.allow_virtual_network_access
allow_forwarded_traffic = var.allow_forwarded_traffic
allow_gateway_transit = var.allow_gateway_transit
use_remote_gateways = var.use_remote_gateways
//depends_on = [data.azurerm_virtual_network.existing_source_vnet]
}
# initiates destination to source peering between to existing vnets
resource "azurerm_virtual_network_peering" "destination-to-source" {
name = "peering-from-${var.source_peer.virtual_network_name}"
resource_group_name = data.azurerm_virtual_network.existing_destination_vnet.resource_group_name
virtual_network_name = data.azurerm_virtual_network.existing_destination_vnet.name
remote_virtual_network_id = data.azurerm_virtual_network.existing_source_vnet.id #change here
allow_virtual_network_access = var.allow_virtual_network_access
allow_forwarded_traffic = var.allow_forwarded_traffic
allow_gateway_transit = var.allow_gateway_transit
use_remote_gateways = var.use_remote_gateways
//depends_on = [data.azurerm_virtual_network.existing_destination_vnet]
}
In addition, the VNet peering works at the VNet level, you don't need to declare the existing subnet in your code unless you want to output subnet.

Azure The 'resourceTargetId' property of endpoint 'vm1-TF' is invalid or missing

I want to implement traffic manager in Terraform between two vm's from different locations (West Europe and North Europe). I attach my code, but I don't know how to configure "target_resource_id" for each vm, because the vm's were created in a for loop, also the networks. The traffic manager would switch to the secondary vm, in case of failure of the first vm. Any ideas?
My code:
variable "subscription_id" {}
variable "tenant_id" {}
variable "environment" {}
variable "azurerm_resource_group_name" {}
variable "locations" {
type = map(string)
default = {
vm1 = "North Europe"
vm2 = "West Europe"
}
}
# Configure the Azure Provider
provider "azurerm" {
subscription_id = var.subscription_id
tenant_id = var.tenant_id
version = "=2.10.0"
features {}
}
resource "azurerm_virtual_network" "main" {
for_each = var.locations
name = "${each.key}-network"
address_space = ["10.0.0.0/16"]
location = each.value
resource_group_name = var.azurerm_resource_group_name
}
resource "azurerm_subnet" "internal" {
for_each = var.locations
name = "${each.key}-subnet"
resource_group_name = var.azurerm_resource_group_name
virtual_network_name = azurerm_virtual_network.main[each.key].name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_public_ip" "example" {
for_each = var.locations
name = "${each.key}-pip"
location = each.value
resource_group_name = var.azurerm_resource_group_name
allocation_method = "Static"
idle_timeout_in_minutes = 30
tags = {
environment = "dev01"
}
}
resource "azurerm_network_interface" "main" {
for_each = var.locations
name = "${each.key}-nic"
location = each.value
resource_group_name = var.azurerm_resource_group_name
ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.internal[each.key].id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.example[each.key].id
}
}
resource "random_password" "password" {
length = 16
special = true
override_special = "_%#"
}
resource "azurerm_virtual_machine" "main" {
for_each = var.locations
name = "${each.key}t-vm"
location = each.value
resource_group_name = var.azurerm_resource_group_name
network_interface_ids = [azurerm_network_interface.main[each.key].id]
vm_size = "Standard_D2s_v3"
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
storage_os_disk {
name = "${each.key}-myosdisk1"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = "${each.key}-hostname"
admin_username = "testadmin"
admin_password = random_password.password.result
}
os_profile_linux_config {
disable_password_authentication = false
}
tags = {
environment = "dev01"
}
}
resource "random_id" "server" {
keepers = {
azi_id = 1
}
byte_length = 8
}
resource "azurerm_traffic_manager_profile" "example" {
name = random_id.server.hex
resource_group_name = var.azurerm_resource_group_name
traffic_routing_method = "Priority"
dns_config {
relative_name = random_id.server.hex
ttl = 100
}
monitor_config {
protocol = "http"
port = 80
path = "/"
interval_in_seconds = 30
timeout_in_seconds = 9
tolerated_number_of_failures = 3
}
tags = {
environment = "dev01"
}
}
resource "azurerm_traffic_manager_endpoint" "first-vm" {
for_each = var.locations
name = "${each.key}-TF"
resource_group_name = var.azurerm_resource_group_name
profile_name = "${azurerm_traffic_manager_profile.example.name}"
target_resource_id = "[azurerm_network_interface.main[each.key].id]"
type = "azureEndpoints"
priority = "${[each.key] == "vm1" ? 1 : 2}"
}
My error:
Error: trafficmanager.EndpointsClient#CreateOrUpdate: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error.
Status=400 Code="BadRequest" Message="The 'resourceTargetId' property of endpoint 'vm1-TF' is invalid or missing.
The property must be specified only for the following endpoint types: AzureEndpoints, NestedEndpoints.
You must have read access to the resource to which it refers."
According to this documentation:
Azure endpoints are used for Azure-based services in Traffic Manager. The following Azure resource types are supported:
PaaS cloud services
Web Apps
Web App Slots
PublicIPAddress resources (which can be connected to VMs either directly or via an Azure Load Balancer). The publicIpAddress must have a DNS name assigned to be used in a Traffic Manager profile.
In your code, you need to change the Target ResourceId to PublicIPAddress. You should not pass the Network Interface ID.
resource "azurerm_traffic_manager_endpoint" "first-vm" {
for_each = var.locations
name = "${each.key}-TF"
resource_group_name = var.azurerm_resource_group_name
profile_name = "${azurerm_traffic_manager_profile.example.name}"
target_resource_id = azurerm_public_ip.example[each.key].id
type = "azureEndpoints"
priority = "${[each.key] == "vm1" ? 1 : 2}"
}
Please Note: The publicIpAddress must have a DNS name assigned to be used in a Traffic Manager profile.
Also you can check this ARM Template which is equivalent to this terraform template.
Hope this helps!

Terraform: Can not parse "ip_configuration.0.subnet_id" as a resource id - invalid URI for request: Nested

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

how to reference objects in terraform

I am creating an Azure VNet using terraform, and creating a couple subnets in it. Later on , I want to create a network interface, and want to put it in one of the subnets already created for VNet. I do not know how to reference that subnet.
I tried below but it is now working:
subnet_id = "${azurerm_virtual_network.virtual-network.subnet.ServersSubnet.id}"
resource "azurerm_virtual_network" "virtual-network" {
name = "${var.ClientShortName}-az-network"
address_space = ["${local.AzureInfraNetwork}"]
location = "${var.resource-location}"
resource_group_name = "${azurerm_resource_group.test-resource-group.name}"
subnet {
name = "ServersSubnet"
address_prefix = "${local.ServersSubnet}"
}
subnet {
name = "GatewaySubnet"
address_prefix = "${local.GatewaySubnet}"
}
}
Error: Cannot index a set value
on main.tf line 120, in resource "azurerm_network_interface" "DCNIC":
120: subnet_id = "${azurerm_virtual_network.virtual-network.subnet.ServersSubnet.id}"
Block type "subnet" is represented by a set of objects, and set elements do
not have addressable keys. To find elements matching specific criteria, use a
"for" expression with an "if" clause.
Below is the complete solution.
If the subnets are created as blocks, you can reference a given subnet's resource ID as follows:
resource "azurerm_resource_group" "main" {
name = "vnet-rg"
location = "eastus"
}
resource "azurerm_virtual_network" "main" {
name = "my-vnet"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
address_space = ["10.0.0.0/16"]
subnet {
name = "subnet1"
address_prefix = "10.0.1.0/24"
}
subnet {
name = "subnet2"
address_prefix = "10.0.2.0/24"
}
subnet {
name = "subnet3"
address_prefix = "10.0.3.0/24"
}
}
output "subnet1_id" {
value = azurerm_virtual_network.main.subnet.*.id[0]
}
output "subnet2_id" {
value = azurerm_virtual_network.main.subnet.*.id[1]
}
output "subnet3_id" {
value = azurerm_virtual_network.main.subnet.*.id[2]
}
When creating subnets as blocks you must reference them using the list syntax, e.g.:
foo = azurerm_virtual_network.virtual-network.subnet[0].id
bar = azurerm_virtual_network.virtual-network.subnet[1].id
This is useful if the subnets form a pool of redundant resources and you don't care about referencing any subnet in particular.
I don't believe that's your case, so you might consider creating your subnets as separated resources, e.g:
resource "azurerm_virtual_network" "main" {
name = "${var.ClientShortName}-az-network"
address_space = [local.AzureInfraNetwork]
location = var.resource-location
resource_group_name = azurerm_resource_group.test-resource-group.name
}
resource "azurerm_subnet" "server" {
virtual_network_name = azurerm_virtual_network.main.name
name = "ServersSubnet"
address_prefix = local.ServersSubnet
}
resource "azurerm_subnet" "gateway" {
virtual_network_name = azurerm_virtual_network.main.name
name = "GatewaySubnet"
address_prefix = local.ServersSubnet
}
Then you could reference one of your subnets using the regular object attribute syntax:
foo = azurerm_subnet.server.id
Also note that I'm using terraform => 0.12 syntax, so I can write foo.bar instead of "${foo.bar}" when I don't need string interpolation.
If anyone else needs the answer to this use this:
"${element(azuread_application.events_backend.app_role[*].id,0)}"
You can break this out into creating the virtual network and the subnet as separate resources. Advantage of this is that you can return your subnets as a map rather than a list, making it easier to retrieve by name later on, it also makes it stable if you need to add/remove subnets at a later stage.
locals {
subnets = {
Servers = "10.0.1.0/24",
Gateway = "10.0.2.0/24"
}
}
resource "azurerm_resource_group" "main" {
name = "vnet-rg"
location = "eastus"
}
resource "azurerm_virtual_network" "main" {
name = "my-vnet"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
address_space = [ local.AzureInfraNetwork ]
}
resource "azurerm_subnet" "main" {
for_each = var.subnets
name = "${each.key}-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [ each.value ]
}
output "subnets" {
value = azurerm_subnet.main
}

Resources