Terraform:如何将资源属性变量化为输入值并解决计划报错
Terraform 动态资源引用问题解析
问题描述
我尝试运行以下Terraform代码:
data "azurerm_resource_group" "rg_tst_na" { name = "test1" } data "azurerm_resource_group" "rg_dev_na" { name = "test2" } resource "azurerm_role_assignment" "test_role_assign" { for_each = var.test_role_assignment principal_id = azurerm_user_assigned_identity.test_setup["${each.key}_${each.value}"].principal_id # 该资源通过for_each单独创建,已通过terraform apply验证 role_definition_name = "Network Contributor" scope = data.azurerm_resource_group."${each.key}_${each.value}".id } variable "var.test_role_assignment" { type = map(string) default={ "na" = "dev", "na" = "tst", } }
执行terraform plan时出现scope无法读取的错误,我想将资源属性的输入变量化,写成如下形式:
scope = data.azurerm_resource_group.rg_"${each.value}"_"${each.key}".id
请问这种方式是否可行?能否在scope的值中使用变量化的资源属性引用?这是否违反Terraform的规则?
解答
1. 你提出的变量化资源引用方式不可行,违反Terraform核心规则
Terraform的资源/数据源引用(如data.azurerm_resource_group.rg_tst_na)属于静态语法标识符,Terraform在配置解析阶段就需要明确识别所有资源依赖关系,无法通过字符串插值("${}")动态拼接资源名称。这种写法会直接触发语法解析错误,无法被Terraform识别。
2. 现有代码的其他问题
- 变量定义错误:变量名不能以
var.开头,正确写法是variable "test_role_assignment",移除前缀var.。 - Map键重复:默认Map中
"na"作为键重复定义,Terraform会自动保留最后一个值("tst"),导致仅创建一个角色分配,不符合预期。
3. 正确实现动态资源引用的方案
要实现动态匹配资源组,需通过资源for_each批量创建或本地值映射的方式处理:
方案一:给数据源添加for_each,动态生成资源组引用
# 定义需引用的资源组信息,键为资源组标识符,值为资源组名称 variable "resource_groups" { type = map(string) default = { rg_dev_na = "test2" rg_tst_na = "test1" } } # 用for_each动态创建资源组数据源 data "azurerm_resource_group" "rg" { for_each = var.resource_groups name = each.value } # 修正角色分配变量,使用唯一键区分条目 variable "test_role_assignment" { type = map(string) default = { dev_na = "dev" tst_na = "tst" } } resource "azurerm_role_assignment" "test_role_assign" { for_each = var.test_role_assignment principal_id = azurerm_user_assigned_identity.test_setup["na_${each.value}"].principal_id role_definition_name = "Network Contributor" # 通过数据源的for_each映射获取对应资源组ID scope = data.azurerm_resource_group.rg["rg_${each.value}_na"].id }
方案二:使用本地值创建资源组映射
如果不想修改现有资源组数据源的定义,可通过locals创建静态映射实现动态引用:
data "azurerm_resource_group" "rg_tst_na" { name = "test1" } data "azurerm_resource_group" "rg_dev_na" { name = "test2" } # 创建资源组映射,键为匹配标识,值为对应数据源 locals { resource_group_map = { "tst_na" = data.azurerm_resource_group.rg_tst_na "dev_na" = data.azurerm_resource_group.rg_dev_na } } # 修正角色分配变量,使用唯一键 variable "test_role_assignment" { type = map(string) default = { na_dev = "dev" na_tst = "tst" } } resource "azurerm_role_assignment" "test_role_assign" { for_each = var.test_role_assignment principal_id = azurerm_user_assigned_identity.test_setup["na_${each.value}"].principal_id role_definition_name = "Network Contributor" # 通过本地映射动态获取资源组ID scope = local.resource_group_map["${each.value}_na"].id }
内容的提问来源于stack exchange,提问作者chandra shekhar
相关产品推荐
相关产品推荐

