1

我有一个包含以下代码的模块。

resource "aws_s3_bucket" "main" {
  bucket = var.bucket_name
  acl    = "private"
  tags   = var.tags

  versioning {
    enabled = var.versioning_enabled
  }
}

resource "aws_s3_bucket_policy" "mod" {
  depends_on = [aws_s3_bucket.main]
  count  = length(var.bucket_policy) > 0 ? 1 : 0
  bucket = aws_s3_bucket.main.id
  policy = var.bucket_policy
}

variable "bucket_policy" {
  default = ""
}

我使用下面的代码调用模块,为了安全起见,我已经对其进行了编辑。

module "xxxx-api-s3-firehose" {
  source      = "git::ssh://git@github.com/xxxx/infra-terraform-modules-s3?ref=v1.0.0"
  bucket_name = "reporting-xxxxxx-api-${var.env_suffix}-${var.region}"

  bucket_policy = <<EOF
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Sid": "xxx Bucket Permissions",
         "Effect": "Allow",
         "Principal": {
            "AWS": "${aws_iam_role.xxxxx-api-firehose-role.arn}"
         },
         "Action": [
            "s3:Get*",
            "s3:List*",
            "s3:Put*"
         ],
         "Resource": [
            "arn:aws:s3:::${module.xxxx-api-s3-firehose.bucket_id}",
            "arn:aws:s3:::${module.xxxxx-api-s3-firehose.bucket_id}/*"
         ]
      },
      {
         "Sid": "xx Bucket Permissions",
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::${var.account_id}:role/${var.xxxxx}"
         },
         "Action": [
            "s3:Get*",
            "s3:List*",
            "s3:Put*"
         ],
         "Resource": [
            "arn:aws:s3:::${module.xxx-api-s3-firehose.bucket_id}",
            "arn:aws:s3:::${module.xxx-api-s3-firehose.bucket_id}/*"
         ]
      }
   ]
}
EOF

运行后我收到以下错误terraform apply

 Error: Invalid count argument
│ 
│   on xxxxx-backend-dev.xxxx-api-s3-firehose/main.tf line 39, in resource "aws_s3_bucket_policy" "mod":
│   39:   count  = length(var.bucket_policy) > 0 ? 1 : 0
│ 
│ The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.
╵

我在多个版本的 terraform 中收到错误,包括最新的 1.0.6。

我不确定问题是什么。有人可以建议吗?

4

2 回答 2

0

正如错误消息所暗示的那样,您不能这样做。你的bucket_policy长度不是恒定的。您应该能够使用列表来克服这个问题:

variable "bucket_policy" {
  default = []
}

resource "aws_s3_bucket_policy" "mod" {
  depends_on = [aws_s3_bucket.main]
  count  = length(var.bucket_policy) > 0 ? 1 : 0
  bucket = aws_s3_bucket.main.id
  policy = var.bucket_policy[0]
}

module "xxxx-api-s3-firehose" {
  source      = "git::ssh://git@github.com/xxxx/infra-terraform-modules-s3?ref=v1.0.0"
  bucket_name = "reporting-xxxxxx-api-${var.env_suffix}-${var.region}"

  bucket_policy = [<<EOF
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Sid": "xxx Bucket Permissions",
         "Effect": "Allow",
         "Principal": {
            "AWS": "${aws_iam_role.xxxxx-api-firehose-role.arn}"
         },
         "Action": [
            "s3:Get*",
            "s3:List*",
            "s3:Put*"
         ],
         "Resource": [
            "arn:aws:s3:::${module.xxxx-api-s3-firehose.bucket_id}",
            "arn:aws:s3:::${module.xxxxx-api-s3-firehose.bucket_id}/*"
         ]
      },
      {
         "Sid": "xx Bucket Permissions",
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::${var.account_id}:role/${var.xxxxx}"
         },
         "Action": [
            "s3:Get*",
            "s3:List*",
            "s3:Put*"
         ],
         "Resource": [
            "arn:aws:s3:::${module.xxx-api-s3-firehose.bucket_id}",
            "arn:aws:s3:::${module.xxx-api-s3-firehose.bucket_id}/*"
         ]
      }
   ]
}
EOF
]
于 2021-09-13T22:12:33.903 回答
0

这里的关键问题是您试图将字符串的长度用作count条件的一部分,但字符串模板包含的值在应用步骤之前不知道,因此字符串的长度不能直到应用步骤才知道。

为了使这项工作发挥作用,您需要找到某种方法将是否声明对象的指示与其将使用的确切策略字符串分开。

实现这一点的一种方法是将特定的字符串值包装在一个可以完全为空的对象中,以表示根本没有声明策略。例如:

variable "bucket_policy" {
  type = object({
    json = string
  })
  default = null
}

resource "aws_s3_bucket_policy" "mod" {
  count = var.bucket_policy != null ? 1 : 0

  bucket = aws_s3_bucket.main.id
  policy = var.bucket_policy.json
}

调用模块时:

  bucket_policy = {
    json = jsonencode({
      # (the policy document content, as before)
    })
  }

使用这种结构,var.bucket_policy即使var.bucket_policy.json 知道也可以知道,因此我们将是否完全声明策略的决定与特定的策略文档值分开。

如果您设置bucket_policynull(无论是明确地还是只是通过在块内省略其定义module),那么策略资源将具有count = 0. 如果您将它设置为我上面显示的非空对象,那么策略资源将具有count = 1并且策略文档将作为参数传入。

于 2021-09-14T00:05:01.247 回答