首页 > 解决方案 > 引用使用 for_each 循环创建的每个资源

问题描述

我正在使用 for_each 创建多个 s3 存储桶,并且在创建资源时没有问题。稍后我在引用这些资源时遇到了麻烦。我希望能够引用所有资源。像这样:

resource "aws_s3_bucket" "dm_client" {
    for_each = toset(var.dm_client_bucket)

    bucket = format("dm-%s-%s",var.env,each.value)
    acl = "private"

    versioning {
        enabled = true
    }
...
data "aws_iam_policy_document" "dm_permission_client" {
    statement {
        sid = "ClientAccess"
        actions = [
            "s3:List*",
            "s3:Get*"
        ]
        resources = [
            aws_s3_bucket.dm_internal["*"].arn,
            "${aws_s3_bucket.dm_internal["*"].arn}/*",
            aws_s3_bucket.dm_client["*"].arn,
            "${aws_s3_bucket.dm_client["*"].arn}/*"
        ]
    }
}```
I've tried using *, "*", etc.. To no avail..

标签: amazon-web-servicesterraform

解决方案


当您使用for_each资源时,值将成为从您的键到表示资源实例的对象的映射。该[*]运算符用于列表,因此在这种情况下不起作用。

相反,您可以编写一个for表达式

[for b in aws_s3_bucket.dm_internal : b.arn]

在您描述的情况下,您需要一个列表,但类似的语法也可以从键派生映射到 ARN 字符串:

{ for k, b in aws_s3_bucket.dm_internal : k => b.arn }

[*]运算符 ( " Splat Expressions"for ) 是应用于列表或集合时的表达式的简写。


in的resources参数aws_iam_policy_document需要一个字符串列表,但如果你只是for直接使用表达式,你会得到一个字符串列表的列表。要获取参数所期望的字符串的平面列表,请使用concat

  resources = concat(
    [for b in aws_s3_bucket.dm_internal : b.arn],
    [for b in aws_s3_bucket.dm_internal : "${b.arn}/*"],
    [for b in aws_s3_bucket.dm_client : b.arn],
    [for b in aws_s3_bucket.dm_client : "${b.arn}/*"],
  )

推荐阅读