具有下游依赖项的 Terraform 条件“for_each”
Posted
技术标签:
【中文标题】具有下游依赖项的 Terraform 条件“for_each”【英文标题】:Terraform conditional `for_each` with downstream dependencies 【发布时间】:2021-12-13 23:07:18 【问题描述】:给定一些条件/过滤的for_each
语句,我如何将剩余的对象用于下游依赖项?
注意:Terraform 0.13.7
例如,如果用户没有 s3 存储桶,terraform 应该创建一个并设置它的通知策略。如果他们确实有一个存储桶,那么 terraform 应该查找存储桶并设置它的通知。
到目前为止,我已经尝试像这样格式化我的有效负载:
"snowpipes":
. . .
"create_staging_bucket": true,
"staging_bucket":
"name": "existing-bucket-deployment",
"url": "old-dirty-bucket",
"arn": "arn:aws:s3:::old-dirty-bucket"
,
. . .
然后像这样构建我的 terraform:
resource "aws_s3_bucket" "staging_bucket"
for_each = for k, v in var.snowpipes : k => v if v.create_staging_bucket == true
bucket = lower(each.value.staging_bucket.url)
resource "aws_s3_bucket_notification" "bucket_notification"
for_each = var.snowpipes
bucket = aws_s3_bucket.staging_bucket[each.key].id
. . .
然后我得到这样的错误,表明给定的密钥被过滤掉了:
Error: Invalid index
on main.tf line 504, in resource "aws_s3_bucket_notification" "bucket_notification":
504: bucket = aws_s3_bucket.staging_bucket[each.key].id
|----------------
| aws_s3_bucket.staging_bucket is object with no attributes
| each.key is "existing-bucket-deployment"
The given key does not identify an element in this collection value.
不确定是否有办法在 resource
和 data
对象之间来回交换?
【问题讨论】:
【参考方案1】:我通常建议通过艰难决定创建存储桶是否属于其范围的一部分,然后让调用模块始终声明其自己的 S3 存储桶,以简化共享模块您决定 S3 存储桶不在其范围内,但我也可以看到,有时以这种方式灵活很方便,但这样做可能会牺牲一些额外的配置复杂性。
让我们首先展示我将在其余部分中假设的变量声明:
variable "snowpipes"
type = map(object(
create_staging_bucket = bool
staging_bucket = object(
name = string
url = string
arn = string
)
# (and whatever else you need, immaterial to this question)
))
接下来让我们为这些元素的子集声明 aws_s3_bucket
资源,这些元素设置了 create_staging_bucket
,这与您已经编写的内容相同:
resource "aws_s3_bucket" "staging_bucket"
for_each =
for k, v in var.snowpipes : k => v
if v.create_staging_bucket == true
bucket = lower(each.value.staging_bucket.url)
到目前为止,我希望我只是基本上重复了您已经拥有的内容。我的下一步是将此资源的结果合并到原始变量的设置中,以便创建所有暂存存储桶的平面图,无论它们是否在此处创建:
locals
staging_buckets = merge(
for k, sp in var.snowpipes : k => sp.staging_bucket
for k, b in aws_s3_bucket.staging_bucket : k =>
name = b.bucket
url = b.bucket # (not sure about this, but following your example above)
arn = b.arn
现在我们回到了一个映射,它的所有键都与我们在 var.snowpipes
中开始时的键相同,其中一些元素只是输入中的逐字记录,而其他元素是根据我们声明的资源合成的.由于merge
的优先行为,它会更喜欢使用第二个映射中的键,而不是映射键发生冲突的第一个映射中的键。
我们可以将它用于存储桶通知资源:
resource "aws_s3_bucket_notification" "bucket_notification"
for_each = local.staging_buckets
bucket = each.value.name
# ...
【讨论】:
谢谢,我什至不知道有合并,也绝对没有意识到使用局部变量的威力。来自很多 TF12,我最终创建了两个以地图为条件的资源(resource.s3 和 data.s3)和两个通知资源,但这看起来更干净。以上是关于具有下游依赖项的 Terraform 条件“for_each”的主要内容,如果未能解决你的问题,请参考以下文章
具有来自 .tfvars 的值的 terraform for_each 实现