英文:
Terraform on Azure - I am trying to call the results of a for_each block in one resource in another resource
问题
这是您提供的代码片段,我将保留代码不进行翻译,只提供注释和描述:
# 创建2个资源组,每个资源组在2个地区中各创建一个
resource "azurerm_resource_group" "rg" {
for_each = {
for k, v in local.multi_region_rg : v.rg_name => v
}
name = each.key
location = each.value.region_name
}
# 创建2个虚拟网络,在2个地区中各创建一个
resource "azurerm_virtual_network" "vnet" {
for_each = {
for k, v in local.multi_region_vnet : v.vnet_name => v
}
name = each.key
location = each.value.region_name
address_space = each.value.virtual_network_address_space
resource_group_name = azurerm_resource_group.rg[each.key] # 尝试从上面的资源组块中调用结果
}
这两个资源块的目的是创建Azure资源组和虚拟网络。在第二个资源块中,您尝试使用azurerm_resource_group.rg[each.key]
来引用第一个资源块中已创建的资源组。
然而,根据报错信息,看起来有一个问题。您可能需要确保在第二个资源块中,azurerm_resource_group.rg
返回的索引是有效的,以便能够正确引用资源组。检查一下是否在azurerm_resource_group.rg
中包含了与local.multi_region_vnet
中的each.key
相对应的资源组名称。如果资源组名称与local.multi_region_vnet
中的each.key
不匹配,就会导致"Invalid index"错误。
您可以确保azurerm_resource_group.rg
中的索引与local.multi_region_vnet
中的资源组名称匹配,以解决这个问题。如果需要更多帮助,请提供更多上下文。
英文:
Terraform on Azure - I am trying to call the results of a for_each block in one resource in another resource.
I have gone through the following & cant seem to be able to wrap my head around the logic.
>https://stackoverflow.com/questions/71646136/terraform-reference-a-for-each-resource-from-another-for-each-resource
>https://stackoverflow.com/questions/68571073/for-each-loop-in-resource-block-terraform
I have 2 resource blocks [I have added the locals file ]
# Local Variables
#
locals {
# Create a flattened list for resource groups in multiple regions
multi_region_rg = flatten([
for rg_key, rg in var.multiple_resource_groups : [
for region_key, region in var.regions : {
rg_name = var.environment != "" ? format("%s-rg-%s-%s-%s", var.tenant, rg_key, var.environment, region.code) : format("%s-rg-%s-%s", var.tenant, rg_key, region.code)
region_name = region.name
}
]
])
}
# Local Variables
#
locals {
# Create a flattened list for resource groups in multiple regions
multi_region_vnet = flatten([
for vnet_key, vnet in var.multiple_vnets : [
for region_key, region in var.regions : {
vnet_name = var.environment != "" ? format("%s-rg-%s-%s-%s", var.tenant, vnet_key, var.environment, region.code) : format("%s-rg-%s-%s", var.tenant, vnet_key, region.code)
region_name = region.name
virtual_network_address_space = vnet.address_space
}
]
])
}
TFVARS file
# Global tags
global_tags = { "ManagedBy" = "Terraform" }
# Map of regions for deployment of resource groups
regions = {
region1 = { name = "australiaeast", code = "ae" },
region2 = { name = "australiasoutheast", code = "ase" }
}
# Tenant
tenant = "cubem_"
# Map of resource groups
# NOTE: Use short names or aliases for resource groups as the code will generate the resource group name as per the following format:
# <tenant>-rg-<resource_group_alias>-<environment>-<region_code>
multiple_resource_groups = {
connectivity = {
tags = {
CostCenter = "NETWORKS",
Department = "Network Services"
}
}
}
###################################### Vnet Values #######################
# Map of resource groups
# NOTE: Use short names or aliases for resource groups as the code will generate the resource group name as per the following format:
# <tenant>-rg-<resource_group_alias>-<environment>-<region_code>
multiple_vnets = {
vnetx = { address_space = ["10.1.0.0/24"] },
}
# Create 2 resource groups in 2 regions [1 in each region]
#
resource "azurerm_resource_group" "rg" {
for_each = {
for k, v in local.multi_region_rg : v.rg_name => v
}
name = each.key
location = each.value.region_name
}
# Create 2 vnets in 2 regions [1 in each region]
#
resource "azurerm_virtual_network" "vnet" {
for_each = {
for k, v in local.multi_region_vnet : v.vnet_name => v
}
name = each.key
location = each.value.region_name
address_space = each.value.virtual_network_address_space
resource_group_name = azurerm_resource_group.rg[each.key] #Im trying to call the results of the resource group block above
}
These blocks work well when they are run independently but I want to have the ability to run them concurrently so that the vnets gets deployed into the resource groups that are created.
If I use this line resource_group_name = azurerm_resource_group.rg[each.key]
its throwing this error
PS C:\PycharmProjects\terraform-projects\my_azure_connectivity_ref_repo\hub-and-spoke\modules\vnet> terraform plan
╷
│ Error: Invalid index
│
│ on main.tf line 69, in resource "azurerm_virtual_network" "vnet":
│ 69: resource_group_name = azurerm_resource_group.rg[each.key]
│ ├────────────────
│ │ azurerm_resource_group.rg is object with 2 attributes
│ │ each.key is "rg-vnetx-ae"
│
│ The given key does not identify an element in this collection value.
╵
╷
│ Error: Invalid index
│
│ on main.tf line 69, in resource "azurerm_virtual_network" "vnet":
│ 69: resource_group_name = azurerm_resource_group.rg[each.key]
│ ├────────────────
│ │ azurerm_resource_group.rg is object with 2 attributes
│ │ each.key is "rg-vnetx-ase"
│
│ The given key does not identify an element in this collection value.
╵
PS C:\PycharmProjects\terraform-projects\my_azure_connectivity_ref_repo\hub-and-spoke\modules\vnet>
答案1
得分: 2
以下是翻译好的部分:
-
azurerm_virtual_network
定义中的resource_group_name
属性存在两个问题。-
azurerm_resource_group.rg[each.key]
表达式中的[each.key]
不存在。这里的[each.key]
实际上来自于for_each = { for k, v in local.multi_region_vnet : v.vnet_name => v }
,而这个值在azurerm_resource_group.rg
资源中不可用。 -
另一个问题也存在于 vnet 资源的
resource_group_name
属性中。尽管azurerm_resource_group.rg[$(expression)]
应该是azurerm_resource_group.rg[$(expression)].name
。
-
-
因此,您需要调整资源中的一个,以使用一个标准的键,该键对于资源组和虚拟网络都是通用的。我在资源组中使用了位置/区域作为这两个资源都需要的标准键。
以下是修复了上述两个问题的正确代码:
## azurerm_resource_group 的 key 现在是 region_name ##
resource "azurerm_resource_group" "rg" {
for_each = {
for k, v in local.multi_region_rg : v.region_name => v
}
name = each.value.rg_name
location = each.key
}
resource "azurerm_virtual_network" "vnet" {
for_each = {
for k, v in local.multi_region_vnet : v.vnet_name => v
}
name = each.key
location = each.value.region_name
address_space = each.value.virtual_network_address_space
resource_group_name = azurerm_resource_group.rg[each.value.region_name].name
}
希望这对您有所帮助。
英文:
There are two issues in your resource "azurerm_virtual_network" "vnet"
definition in the resource_group_name
attribute.
[each.key]
inazurerm_resource_group.rg[each.key]
expression does not exists. here[each.key]
is the vnet name actually coming fromfor_each = { for k, v in local.multi_region_vnet : v.vnet_name => v}
which is not available in the resourceazurerm_resource_group.rg
> { for k, v in local.multi_region_vnet : v.vnet_name => v }
{
"test-rg-vnet_key-dev-ae" = {
"region_name" = "australiaeast"
"virtual_network_address_space" = [
"10.1.0.0/24",
]
"vnet_name" = "test-rg-vnet_key-dev-ae"
}
"test-rg-vnet_key-dev-ase" = {
"region_name" = "australiasoutheast"
"virtual_network_address_space" = [
"10.1.0.0/24",
]
"vnet_name" = "test-rg-vnet_key-dev-ase"
}
}
- The other issue also lies in the
resource_group_name
attribute of vnet resource with the reference. in spite ofazurerm_resource_group.rg[$(expression)]
should beazurerm_resource_group.rg[$(expression)].name
Hence, You have to adjust either of your resources with a standard key which is common for both resource_group and vnet. I have done it in the resource group with location/region as it is required in both of the resources.
Hence the correct code addressing both the above issues would be.
## key is now region_name in azurerm_resource_group ##
resource "azurerm_resource_group" "rg" {
for_each = {
for k, v in local.multi_region_rg : v.region_name => v
}
name = each.value.rg_name
location = each.key
}
resource "azurerm_virtual_network" "vnet" {
for_each = {
for k, v in local.multi_region_vnet : v.vnet_name => v
}
name = each.key
location = each.value.region_name
address_space = each.value.virtual_network_address_space
resource_group_name = azurerm_resource_group.rg[(each.value.region_name)].name
}
Code In Action
➜ random_local_tests git:(main) ✗ terraform apply -auto-approve
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# azurerm_resource_group.rg["australiaeast"] will be created
+ resource "azurerm_resource_group" "rg" {
+ id = (known after apply)
+ location = "australiaeast"
+ name = "test-rg-vnet_key-dev-ae"
}
# azurerm_resource_group.rg["australiasoutheast"] will be created
+ resource "azurerm_resource_group" "rg" {
+ id = (known after apply)
+ location = "australiasoutheast"
+ name = "test-rg-vnet_key-dev-ase"
}
# azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ae"] will be created
+ resource "azurerm_virtual_network" "vnet" {
+ address_space = [
+ "10.1.0.0/24",
]
+ dns_servers = (known after apply)
+ guid = (known after apply)
+ id = (known after apply)
+ location = "australiaeast"
+ name = "test-rg-vnet_key-dev-ae"
+ resource_group_name = "test-rg-vnet_key-dev-ae"
+ subnet = (known after apply)
}
# azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ase"] will be created
+ resource "azurerm_virtual_network" "vnet" {
+ address_space = [
+ "10.1.0.0/24",
]
+ dns_servers = (known after apply)
+ guid = (known after apply)
+ id = (known after apply)
+ location = "australiasoutheast"
+ name = "test-rg-vnet_key-dev-ase"
+ resource_group_name = "test-rg-vnet_key-dev-ase"
+ subnet = (known after apply)
}
Plan: 4 to add, 0 to change, 0 to destroy.
azurerm_resource_group.rg["australiaeast"]: Creating...
azurerm_resource_group.rg["australiasoutheast"]: Creating...
azurerm_resource_group.rg["australiaeast"]: Creation complete after 5s [id=/subscriptions/xxxxxxxxxxxx/resourceGroups/test-rg-vnet_key-dev-ae]
azurerm_resource_group.rg["australiasoutheast"]: Creation complete after 6s [id=/subscriptions/xxxxxxxxxxxx/resourceGroups/test-rg-vnet_key-dev-ase]
azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ae"]: Creating...
azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ase"]: Creating...
azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ase"]: Still creating... [10s elapsed]
azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ae"]: Still creating... [10s elapsed]
azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ae"]: Creation complete after 18s [id=/subscriptions/xxxxxxxxxxxx/resourceGroups/test-rg-vnet_key-dev-ae/providers/Microsoft.Network/virtualNetworks/test-rg-vnet_key-dev-ae]
azurerm_virtual_network.vnet["test-rg-vnet_key-dev-ase"]: Creation complete after 19s [id=/subscriptions/xxxxxxxxxxxx/resourceGroups/test-rg-vnet_key-dev-ase/providers/Microsoft.Network/virtualNetworks/test-rg-vnet_key-dev-ase]
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Hope it helps.
And additional info which is not relevant here too much I have used static values instead of some variables.
rg_name = var.environment != "" ? format("%s-rg-%s-%s-%s", "test", "vnet_key", var.environment, region.code) : format("%s-rg-%s-%s", "test", "vnet_key", region.code)
vnet_name = var.environment != "" ? format("%s-rg-%s-%s-%s", "test", "vnet_key", var.environment, region.code) : format("%s-rg-%s-%s", "test", "vnet_key", region.code)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论