我使用的是 terraform 版本 1.5.7。我想构建一个模块,在其中可以添加存储桶策略作为变量,并且 仅当存在提供的策略时,才应创建 aws_s3_bucket_policy 资源。
此外,我假设我需要使用 count 或 for_each 以及具有不同默认值的变量,因此我可以确定这是 NULLABLE。
遗憾的是,这似乎不起作用,因为 terraform 的“属性 [.] 无法确定”,我需要使用目标,即使策略是纯文本并写在代码中。
如有任何帮助,我们将不胜感激!
模块-变量
variable "name" {
description = "Name of S3 bucket"
type = string
}
variable "policy" {
description = "Bucket policy, which is assigned to a bucket and allows access to it. Defaults to null"
type = string
nullable = true
default = null
}
模块 - 主要
resource "aws_s3_bucket" "bucket" {
bucket = var.name
}
resource "aws_s3_bucket_policy" "policy" {
count = var.policy != null ? 1 : 0
bucket = aws_s3_bucket.bucket.id
policy = var.policy
}
用法
locals {
name = "testOptionalPolicy"
}
module "s3" {
source = "../../modules/s3"
name = local.name
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::${local.name}/*",
"Principal": "*"
}
]
}
EOF
}
接收错误
╷
│ Error: Invalid count argument
│
│ on ../../modules/s3/main.tf line 72, in resource "aws_s3_bucket_policy" "policy":
│ 72: count = var.policy != null ? 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.
╵
如果我用
for_each = var.policy != null ? [1] : []
替换计数,错误会改变,但问题保持不变。
接收错误
╷
│ Error: Invalid for_each argument
│
│ on ../../modules/s3/main.tf line 72, in resource "aws_s3_bucket_policy" "policy":
│ 72: for_each = var.policy != null ? [1] : []
│ ├────────────────
│ │ var.policy is a string, known only after apply
│
│ The "for_each" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full
│ set of keys that will identify the instances of this resource.
│
│ When working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only
│ in the map values.
│
│ Alternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a
│ second time to fully converge.
╵
P.S.:这似乎与我的上一个问题有关,尽管有些不同。也许this参考会对某人有所帮助。
如果我正确理解了这个问题,这个问题我已经遇到过很多次了。我几乎总是倾向于尽可能避免
count
而更喜欢 for_each
。
首先我声明一个静态集。
locals {
s3_key = toset(<if criteria are satisfied>?["my_key"]:[])
}
然后在任何必须有条件创建的资源中,我都会引用该密钥。
module "s3" {
for_each = local.s3_key
source = "../../modules/s3"
name = local.name
policy = <<EOF
...
}
但是,请记住,使用这种方法,任何需要访问某些输出变量的资源都必须是 for_eached 以及此类密钥。
resource "aws_iam_role" "my_role" {
for_each = local.s3_key
name = module.s3[each.value].any_output_variable
.....
}
通过这种方式,您可以构建整个依赖资源链。