Terraform : for_each 一个接一个

Terraform : for_each one by one

我在 terraform 上创建了一个模块,这个模块创建了 aws_servicecatalog_provisioned_product 资源。
当我从根调用这个模块时,我使用 for_each 到 运行 到对象列表中。
模块 运行 进入此对象列表并并行创建 aws_servicecatalog_provisioned_product 资源。
有没有办法一个一个地创建资源?我希望模块将等待第一次迭代完成并在之后创建下一次迭代。

Is there a way to create the resources one by one?

遗憾的是,没有这样的方法,除非您删除 for_each 并使用 depends_on 单独创建所有模块。

TF 不是过程语言,它总是会为 for_eachcount 并行处理事情。

如果要确保一个接一个地创建它们,则必须删除 for_each 并为每个元素使用 depends_on

如果您只想在其他资源之前配置第一个资源:

仅分离第一个资源,其余资源使用for_each。您可以使用 depends_on 为其余资源设置显式依赖关系以依赖于第一个资源。因为 for_each 需要 setmap,此输入需要进行一些修改才能排除第一个资源的配置。

如果您真的需要一个一个地配置资源,一个更激进的方法是 运行 apply 命令和 -parallelism=1。这会将并行配置的资源数量减少到 1。这将适用于整个项目。我不推荐这样做,因为它会大大增加申请的运行宁时间。

为什么要等上次创建呢? Terraform 依赖于提供者知道什么可以并行发生,并且将 运行 在可能的地方并行。

如果我愿意的话,在应用操作之前设置并行性将是我限制它的人为性的方式,因为它是一种技术解决方法,可以使您的 Terraform 代码易于阅读。

TF_CLI_ARGS_apply="-parallelism=1"
terraform apply

如果您发现这会减慢所有 Terraform 创建的速度,但您需要一次部署一组特定资源,那么可能是时候将这些特定资源分解到它们自己的 Terraform 配置目录中并应用它了在不同的步骤中再次使用并行设置来处理其余资源。

我正在使用 terraform templatefiledepends on 顺序创建资源,然后 terraform 一个接一个地创建资源。

代码如下:

locals {

     expanded_accounts = [ 
      {
          AccountEmail                           = example1@example.com
          AccountName                         = example1
          ManagedOrganizationalUnit           = example_ou1
          SSOUserEmail                        = example1@example.com
          SSOUserFirstName                    = Daniel
          SSOUserLastName                     = Wor
          ou_id                               = ou_id1
      },
      {
          AccountEmail                           = example2@example.com
          AccountName                         = example2
          ManagedOrganizationalUnit           = example_ou2
          SSOUserEmail                        = example2@example.com
          SSOUserFirstName                    = Ben
          SSOUserLastName                     = John
          ou_id                               = ou_id2
     }
     ]

  previous_resource = [
    for acc in local.expanded_accounts :
    acc.AccountName
  ]

     resources = { res = local.expanded_accounts, previous = concat([""], local.previous_resource)
}

resource "local_file" "this" {
  content              = templatefile("./provisioned_accounts.tpl", local.resources)
  filename             = "./generated_provisioned_accounts.tf"
  directory_permission = "0777"
  file_permission      = "0777"

  lifecycle {
    ignore_changes = [directory_permission, file_permission, filename]
  }
}

provisioned_accounts.tpl配置:

%{ for acc in res }
resource "aws_servicecatalog_provisioned_product" "${acc.AccountName}" {
  name                     = "${acc.AccountName}"
  product_id               = replace(data.local_file.product_name.content, "\n", "")
  provisioning_artifact_id = replace(data.local_file.pa_name.content, "\n", "")
  

  provisioning_parameters {
    key   = "SSOUserEmail"
    value = "${acc.SSOUserEmail}"
  }
  provisioning_parameters {
    key   = "AccountEmail"
    value = "${acc.AccountEmail}"
  }
  provisioning_parameters {
    key   = "AccountName"
    value = "${acc.AccountName}"
  }
  provisioning_parameters {
    key   = "ManagedOrganizationalUnit"
    value = "${acc.ManagedOrganizationalUnit} (${acc.ou_id})"
  }
  provisioning_parameters {
    key   = "SSOUserLastName"
    value = "${acc.SSOUserLastName}"
  }
  provisioning_parameters {
    key   = "SSOUserFirstName"
    value = "${acc.SSOUserFirstName}"
  }

  timeouts {
    create = "60m"
  }

%{if index != 0 }
  depends_on = [aws_servicecatalog_provisioned_product.${previous[index]}]
%{ endif }

}

%{~ endfor ~}