繁体   English   中英

在 Terraform 中,如何使用 for_each 并操作创建的每个资源?

[英]In Terraform, how can I use a for_each and manipulate each resource that is created?

我想看看是否可以在不通过资源引用创建更多资源的情况下操作 for_each 中的每个资源。

例如,我正在创建 3 个 AWS S3 存储桶,在我的 S3 模块中,我有以下资源:

    resource "aws_s3_bucket" "s3-bucket" {
    for_each = var.bucket_details
    bucket = each.value.bucket
    acl    = each.value.acl
    policy = each.value.policy
   }

这是 my.tfvars:

    bucket_details = {

          bucket_1 = {
            bucket = "stg-kikeman-bkt-1"
            acl = "private"
            policy = <<EOF
            { ... <= THIS IS A JSON S3 POLICY 
            }
            EOF
          },
          bucket_2 = { ... }
          bucket_3 = { ... }

应用后,假设创建 3 个桶,其中桶名、acl 及其策略的值。

但我遇到了错误:

 on modules/s3/s3.tf line 15, in resource "aws_s3_bucket" "s3-bucket":
│   15:     policy = each.value.policy
│     ├────────────────
│     │ each.value is map of string with 3 elements
│ 
│ This map does not have an element with the key "policy"

看起来像 json 策略的关键策略的值没有被识别为“值”,我尝试使用 jsonencode({the_json_policy}) 但我得到了错误

Functions may not be called here

我正在研究如何使用 json 政策作为 map 的“价值”,当然如果可能的话。

可能吗?

这是。 根据您要在策略中更改的内容,您必须有条件地设置 attributes 基于需要不同设置的存储桶名称。

for_each适用于您希望根据 map 中的数据系统地声明多个对象的情况。 如果您需要在实例之间存在差异,那么您将需要以某种方式在您提供的 map 中表示这些差异,以便设计仍然是系统的。

一种方法是将源集合改为从名称到包含策略文档和 ACL 字符串的对象的映射:

locals {
  buckets = {
    stg-bkt-1 = {
      acl = "private"
      policy = {
        Version = "2012-10-17"
        Id      = Test
        Statement = [
          {
            Sid = "1"
            Effect = "Deny"
            Principal = "*"
            Action = "*"
            Resource = "arn:aws:s3:::stg-bkt-1/*"
            Condition = {
              Bool = {
                "aws:SecureTransport": "false"
              }
            }
          },
        ]
      }
    }
    stg-bkt-2 = {
      acl = "public-read"
      policy = {
        Version = "2012-10-17"
        Id      = Test
        Statement = [
          {
            Sid       = "1"
            Effect    = "Deny"
            Principal = "*"
            Action    = "*"
            Resource  = "arn:aws:s3:::stg-bkt-2/*"
            Condition = {
              Bool = {
                "aws:SecureTransport": "false"
              }
            }
          },
          {
            Sid       = "2"
            Effect    = "Allow"
            Principal = "*"
            Action    = ["s3:GetObject"]
            Resource  = "arn:aws:s3:::stg-bkt-2/*"
          },
        ]
      }
    }
  }
}

resource "aws_s3_bucket" "s3-bucket" {
  for_each = var.buckets

  bucket = each.key
  acl    = each.value.acl
  policy = jsonencode(each.value.policy)
}

在资源配置最终完全引用each.keyeach.value的情况下,我通常会说这根本不是系统性的,因此只写出多个resource "aws_s3_bucket"会更简单、更容易resource "aws_s3_bucket"块。 但是,如果您可以对此进行调整,以使所有存储桶仍然具有一些共同特征——例如,如果映射中的定义仅包含附加的 IAM 策略语句,这些语句将与所有存储桶通用的策略语句连接起来——那么使用for_each系统地声明它们似乎是合理的,这样当您将来更改细节时,这些通用部分将被迫保持通用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM