在Terraform中使用for each和count一起的解决方案是什么?



我有两个条件需要满足:

  1. 根据env授予用户对特定project-id的权限。例如:my-project-{env}(env: stg/prd)
  2. 我想循环遍历变量,而不是为每个用户写下重复的resource

例子:

variable some_ext_users {
type = map(any)
default = {
user_1 = { email_id = "user_1@gmail.com" }
user_2 = { email_id = "user_2@gmail.com" }
}
}

为了避免对每个用户(想象100++用户)进行重复资源,我决定将它们列在上面所写的variable中。

然后,我想给这些用户分配GCS权限,例如:

resource "google_storage_bucket_iam_member" "user_email_access" {
for_each = var.some_ext_users
count    = var.env == "stg" ? 1 : 0
provider = google-beta
bucket   = "my-bucketttt"
role     = "roles/storage.objectViewer"
member   = "user:${each.value.email_id}"
}

我得到的错误是明确的:

错误:无效的"count"组合和";for_each"在. ./. ./. ./模块/助教。在资源的第54行"google_storage_bucket_iam_member"user_email_access">: 54:
for_each = var.some_ext_users"count"one_answers";for_each"元参数是互斥的,只能使用一个显式指定要创建的资源数量

我的问题是,什么是解决方案,以满足上述要求,如果countfor_each不能一起使用?

您可以根据环境控制用户列表,而不是试图控制资源。像这样:

resource "google_storage_bucket_iam_member" "user_email_access" {
for_each = var.env == "stg" ? var.some_ext_users : {}
provider = google-beta
bucket   = "my-bucketttt"
role     = "roles/storage.objectViewer"
member   = "user:${each.value.email_id}"
}

for_each的规则是为它分配一个映射,每个实例有一个元素,因此考虑您的需求的最佳方法是,当您的条件不成立时,您需要编写一个表达式,生成一个零元素的映射。

在Terraform中投射和过滤集合的通常方法是for表达式,实际上我们可以使用for表达式和if子句来有条件地过滤掉不需要的元素,在这种特殊情况下将是所有元素:
resource "google_storage_bucket_iam_member" "user_email_access" {
for_each = {
for name, user in var.some_ext_users : name => user
if var.env == "stg"
}
# ...
}

另一种可能的构建方法是将环境关键字作为数据结构的一部分,这将使所有信息保存在一个位置,并可能允许您拥有一次应用于多个环境的项:

variable "some_ext_users" {
type = map(object({
email_id     = string
environments = set(string)
}))
default = {
user_1 = {
email_id     = "user_1@gmail.com"
environments = ["stg"]
}
user_2 = {
email_id     = "user_2@gmail.com"
environments = ["stg", "prd"]
}
}
}
resource "google_storage_bucket_iam_member" "user_email_access" {
for_each = {
for name, user in var.some_ext_users : name => user
if contains(user.environments, var.env)
}
# ...
}

这是"过滤元素"中示例的变体。它使用is_admin标志,以便为管理员用户和非管理员用户声明不同的资源。在本例中,请注意if子句引用了在for表达式中声明的符号,这意味着我们现在可以为映射的每个元素获得不同的结果,而第一个示例要么保留所有元素,要么不保留元素。

最新更新