'Terraform - creating a list(string) for Azure locations
I'm trying to deploy a resource group to several locations using Terraform in Azure but get the error: "Inappropriate value for attribute "location": string required."
I'm very new to Terraform so I'm not sure why this doesn't work.
My code:
locals {
webappsperloc = 4
}
resource "azurerm_resource_group" "rg" {
count = length(var.webapplocs)
name = "whatever${count.index}"
location = var.webapplocs[count.index]
tags = var.tags
}
resource "random_string" "webapprnd" {
length = 8
lower = true
number = true
upper = false
special = false
}
resource "azurerm_app_service_plan" "plan" {
count = length(var.webapplocs)
name = "whatever-${var.webapplocs[count.index]}"
location = var.webapplocs[count.index]
resource_group_name = element(azurerm_resource_group.rg.*.name,count.index)
tags = var.tags
sku {
tier = "standard"
size = "S1"
}
}
resource "azurerm_app_service" "app" {
count = local.webappsperloc
name = format("webapp-%s-%02d-%s", random_string.webapprnd.result, count.index + 1, element(var.webapplocs, count.index))
resource_group_name = element(azurerm_resource_group.rg.*.name,count.index)
location = element(var.webapplocs, count.index)
app_service_plan_id = element(azurerm_app_service_plan.plan.*.id, count.index)
https_only = true
site_config {
dotnet_framework_version = "v4.0"
always_on = true
ftps_state = "Disabled"
min_tls_version = "1.2"
}
# tags = {
# environment = var.tags
# source = "terraform"
# }
}
variable "webapplocs" {
default = ["northeurope", "westeurope", "eastus", "uksouth"]
}
#variable "loc" {
# description = "Default Azure region"
# default = "northeurope"
#}
variable "tags" {
default = {
source = "Terraform"
env = "Dev"
}
}
#terraform.tfvars
loc = "northeurope"
tags = {
source = "terrafrom"
env = "Dev"
}
webapplocs = ["northeurope","westeurope","eastus","uksouth"]
terraform {
required_providers {
azure = {
source = "hashicorp/azurerm"
version = "=2.76.0"
}
}
backend "azurerm" {
resource_group_name = "xxxx"
storage_account_name = "xxxx"
container_name = "xxxx"
key = "xxxx"
}
}
# azure provider
provider "azure" {
features {}
}
If you need anything else please let me know. I've used this function before without issue.
Thanks.
edit: code updated to reflect what I managed to get working.
Solution 1:[1]
Based on the error you are getting, I think this is related to invalid attribute reference on this line:
location = var.location
The azurerm_resource_group resource requires only a single value for location and you are providing a list of strings (based on the location variable definition), so you get the error:
"Inappropriate value for attribute "location": string required."
Since you want resource groups in all regions (i.e., location), I would suggest using for_each [1] instead of count.
That way you will be able to have one of each resources per region. How this would work (and there might be more elegant ways of doing it):
resource "azurerm_resource_group" "rg" {
for_each = toset(var.location)
name = "${each.value}-${var.resource_group_name}"
location = each.value
tags = {
environment = var.environment
source = "terraform"
}
}
resource "azurerm_app_service_plan" "plan" {
for_each = toset(var.location)
name = "${each.value}-${var.app_service_plan}"
location = azurerm_resource_group.rg[each.value].location # or alternatively each.value
resource_group_name = azurerm_resource_group.rg[each.value].name
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "app" {
for_each = toset(var.location)
name = "${each.value}-${var.app_service}"
resource_group_name = azurerm_resource_group.rg[each.value].name
location = azurerm_resource_group.rg[each.value].location # or alternatively each.value
app_service_plan_id = azurerm_app_service_plan.plan[each.value].id
https_only = true
site_config {
dotnet_framework_version = "v4.0"
always_on = true
ftps_state = "Disabled"
min_tls_version = "1.2"
}
tags = {
environment = var.environment
source = "terraform"
}
}
Note that I am using toset [2] here to convert the list to a set in order to be able to use for_each on it. Also I am using the values to make names of resources across regions more distinguishable, i.e., appending each.value to the variables you want to use for names.
[1] https://www.terraform.io/language/meta-arguments/for_each
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
