You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:22:16