Terraform循环中无法拼接字符串引用变量的问题求助
Terraform HCL动态引用角色定义ID问题
我在其他编程/脚本环境用过eval()处理类似场景,这不算特殊需求。现在我想基于本地变量创建azurerm_pim_active_role_assignment资源,本地变量由map对象group_roles生成。目前的问题是,role_definition_id只能硬编码引用特定角色(比如local.DataFactoryContributor),这样就得给每种角色单独写资源块,没法实现类似eval("${data.azurerm_subscription.primary.id}${local.${group.role})")的动态引用。想知道HCL是否支持这种动态引用,还是必须为每个角色写独立资源块?
存储角色和Entra组详情的变量(示例)
variable "groupsetuparray"{ type = list(object({ name = string, group_name = string, resource_group_name = string, resource_name = string, group_roles = list(string), members = list(string) })) default = [ { name = "DFDeveloperTeam", group_name = "DFDeveloperTeam", resource_group_name = "", resource_name = "", group_roles = ["DataFactoryContributor","SQLServerContributor"], members = [] } ] }
生成组角色的本地变量
locals { group_roles = flatten([for group in var.groupsetuparray : [ for role in group.group_roles : { name = group.name role = role rg = group.resource_group_name } ] ]) DataFactoryContributor = data.azurerm_role_definition.DataFactoryContributor.id SQLServerContributor = data.azurerm_role_definition.SQLServerContributor.id }
引用内置角色定义的数据源
data "azurerm_role_definition" "DataFactoryContributor" { name = "Data Factory Contributor" } data "azurerm_role_definition" "SQLServerContributor" { name = "SQL Server Contributor" }
尝试用循环创建PIM角色分配的资源(存在问题)
resource "azurerm_pim_active_role_assignment" "DataFactoryContributorAssignment" { for_each = { for group in local.group_roles : "${group.name}-${group.role}" => group if group.role == "DataFactoryContributor" } scope = data.azurerm_subscription.primary.id role_definition_id = "${data.azurerm_subscription.primary.id}${group.role}.id" #=====以下代码可运行,但需为每个角色定义直接引用,并非最优方案===== #role_definition_id = "${data.azurerm_subscription.primary.id}${local.DataFactoryContributor}" #===== principal_id = azuread_group.group[each.value.name].object_id schedule { start_date_time = time_static.example.rfc3339 expiration { duration_hours = 8 } } justification = "Expiration Duration Set" ticket { number = "1" system = "example ticket system" } }
错误信息
Error: Reference to undeclared resource │ │ on main.tf line 61, in resource "azurerm_pim_active_role_assignment" "DataFactoryContributor": │ 61: role_definition_id = "${data.azurerm_subscription.primary.id}${group.role}.id" │ │ A managed resource "group" "role" has not been declared in the root module.
已尝试方案
- 用过
lookup函数,但没成功 - 试过多种表达式和插值方式,均无效
解决方案:重构本地变量为映射表,实现动态引用
HCL不支持类似eval的动态变量名引用,但可以通过构建角色名称到角色ID的映射表来实现动态引用,无需为每个角色单独写资源块。
步骤1:重构本地变量,整理角色ID映射表
locals { group_roles = flatten([for group in var.groupsetuparray : [ for role in group.group_roles : { name = group.name role = role rg = group.resource_group_name } ] ]) # 构建角色名称到角色ID的映射表,统一管理角色ID role_ids = { DataFactoryContributor = data.azurerm_role_definition.DataFactoryContributor.id SQLServerContributor = data.azurerm_role_definition.SQLServerContributor.id } }
步骤2:修改资源块,动态获取角色ID
resource "azurerm_pim_active_role_assignment" "group_role_assignments" { # 为每个组-角色组合创建唯一资源实例 for_each = { for gr in local.group_roles : "${gr.name}-${gr.role}" => gr } scope = data.azurerm_subscription.primary.id # 用lookup从映射表中动态获取当前角色对应的ID role_definition_id = "${data.azurerm_subscription.primary.id}${lookup(local.role_ids, each.value.role)}" principal_id = azuread_group.group[each.value.name].object_id schedule { start_date_time = time_static.example.rfc3339 expiration { duration_hours = 8 } } justification = "Expiration Duration Set" ticket { number = "1" system = "example ticket system" } }
说明
- 把分散的角色ID变量整合成
role_ids映射表,让角色名称和ID一一对应,便于维护 - 使用
lookup(local.role_ids, each.value.role)动态获取当前循环项对应的角色ID,彻底避免硬编码 - 去掉
for_each中的角色过滤条件,一个资源块就能处理所有组的所有角色,无需重复编写资源块 - 资源名称改为通用的
group_role_assignments,符合多实例资源的命名规范
内容的提问来源于stack exchange,提问作者ankur kapoor
相关产品推荐
相关产品推荐

