Terraform中基于其他资源引用的嵌套for循环实现问题
Terraform模块中ServiceAccount角色绑定的引用问题
我有一个Terraform模块,接收名为service_accounts_objects的变量。每个对象包含创建ServiceAccount的字符串,以及该ServiceAccount需要绑定的角色列表。目前已成功创建ServiceAccount,但不知道如何引用生成的SA成员来绑定对应角色。
我知道可以通过for_each = google_service_account.service_account来引用ServiceAccount资源,但资源只能用一个for_each循环,不确定嵌套循环写法是否可行。
原尝试的模块代码
模块调用代码
module "iam" { source = "../../modules/iam" project = var.project service_accounts_objects = [ { service_account = "service-${var.project_short}-tl" roles = [ "roles/run.invoker", "roles/cloudsql.client", "roles/cloudsql.instanceUser", "roles/pubsub.publisher" ] }, { service_account = "service-${var.project_short}-template" roles = [ "roles/cloudsql.client", "roles/cloudsql.instanceUser", "roles/pubsub.publisher" ] } ] }
模块资源代码
resource "google_service_account" "service_account" { for_each = { for index, sa in var.service_accounts_objects: sa.service_account => sa } project = var.project account_id = each.value.service_account } resource "google_project_iam_member" "member" { for_each = { for i, role in var.service_accounts_objects: role.roles => role for j, members in google_service_account.service_account: members.member => members } member = each.value.member project = var.project role = each.value.role }
补充的解决方案(单独调用模块)
因为没找到可行的嵌套循环方法,我改为为每个ServiceAccount单独调用模块:
模块调用代码
module "iam-service-tl" { source = "../../modules/iam" project = var.project service_account_object = { service_account = "sa-service-tl" roles = [ "roles/run.invoker", "roles/cloudsql.client", "roles/cloudsql.instanceUser", "roles/pubsub.publisher" ] } }
模块变量及资源代码
variable "project" {} variable "service_account_object" { description = "要创建的ServiceAccount信息" type = object( { service_account = string roles = list(string) } ) } resource "google_service_account" "service_account" { project = var.project account_id = var.service_account_object.service_account } resource "google_project_iam_member" "member" { member = google_service_account.service_account.member project = var.project for_each = toset(var.service_account_object.roles) role = each.value }
最优批量处理写法
其实不需要拆分模块,通过扁平化ServiceAccount与角色的组合就能实现批量绑定,避免重复调用模块:
# 原ServiceAccount创建代码不变 resource "google_service_account" "service_account" { for_each = { for sa in var.service_accounts_objects: sa.service_account => sa } project = var.project account_id = each.value.service_account } # 扁平化生成每个SA+角色的唯一组合 locals { sa_role_combinations = flatten([ for sa_id, sa in google_service_account.service_account: [for role in sa.value.roles: { sa_id = sa_id role = role member = sa.member } ] ]) } # 基于扁平化后的组合创建IAM绑定 resource "google_project_iam_member" "member" { for_each = { for combo in local.sa_role_combinations: "${combo.sa_id}-${combo.role}" => combo } member = each.value.member project = var.project role = each.value.role }
说明
- 使用
flatten将每个ServiceAccount的角色列表展开为单个SA+角色的对象,确保每个IAM绑定都是唯一的 - 通过
"${combo.sa_id}-${combo.role}"作为for_each的键,避免重复资源 - 直接引用
google_service_account.service_account的member属性,无需复杂嵌套循环
内容的提问来源于stack exchange,提问作者José Lacerda
相关产品推荐
相关产品推荐

