如何在同一个列表上迭代多个资源?

How to iterate multiple resources over the same list?

这里是 Terraform 的新手。我正在尝试使用 Terraform 创建多个项目(在 Google Cloud 中)。问题是我必须执行多个资源才能完全设置一个项目。我尝试了 count,但如何使用 count 顺序绑定多个资源?以下是我需要为每个项目执行的以下资源:

  1. 使用 resource "google_project"
  2. 创建项目
  3. 使用 resource "google_project_service"
  4. 启用 API 服务
  5. 使用 resource "google_compute_shared_vpc_service_project" 将服务项目附加到宿主项目(我使用的是共享 VPC)

如果我想创建单个项目,这很有效。但是,如果我将项目列表作为输入传递,我如何才能按顺序为该列表中的每个项目执行上述所有资源?

例如

输入

project_list=["proj-1","proj-2"]

依次执行以下操作:

resource "google-project" for "proj-1"
resource "google_project_service" for "proj-1"
resource "google_compute_shared_vpc_service_project" for "proj-1"

resource "google-project" for "proj-2"
resource "google_project_service" for "proj-2"
resource "google_compute_shared_vpc_service_project" for "proj-2"

我使用的是不支持 for 循环的 Terraform 版本 0.11

在 Terraform 中,您可以使用 count 和两个插值函数 element()length() 来完成此操作。

首先,您将为模块提供一个输入变量:

variable "project_list" {
  type = "list"
}

然后,你会得到类似的东西:

resource "google_project" {
  count = "${length(var.project_list)}"
  name  = "${element(var.project_list, count.index)}"
}

resource "google_project_service" {
  count = "${length(var.project_list)}"
  name  = "${element(var.project_list, count.index)}"
}

resource "google_compute_shared_vpc_service_project" {
  count = "${length(var.project_list)}"
  name  = "${element(var.project_list, count.index)}"
}

当然,您在这些资源声明中也会有其他配置。

请注意,此模式在 Terraform Up and Running, Chapter 5, and there are other examples of using count.index in the docs here 中有描述。

对此 question/answer 的小更新(terraform 0.13 及更高版本)。由于 terraforms 的工作方式,不建议再使用计数或长度,让我们想象下一个场景:

假设你有一个包含 3 个元素的数组:project_list=["proj-1","proj-2","proj-3"],一旦你应用它,如果你想从你的数组中删除 "proj-2" 项目,一旦你 运行 计划,terraform会将您的第二个元素修改为 "proj-3" 而不是将其从列表 (more info in this good post). The solution to get the proper behavior is to use the for_each 函数中删除,如下所示:

variable "project_list" {
  type = list(string)
}

resource "google_project" {
  for_each = toset(var.project_list)
  name  = each.value
}

resource "google_project_service" {
  for_each = toset(var.project_list)
  name  = each.value
}

resource "google_compute_shared_vpc_service_project" {
  for_each = toset(var.project_list)
  name  = each.value
}

希望对您有所帮助!