You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何迭代使用for_each声明的Terraform模块实例输出?

Terraform迭代for_each模块输出创建AWS Glue爬虫

我需要基于用for_each声明的S3桶模块实例,创建对应的AWS Glue爬虫和数据目录数据库。尝试了几种for_each写法都报错,比如:

写法1:

for_each = {for key, value in setproduct(local.bucket-names, module.crawler_source_buckets.id): key=>value}

报错:

Error: Invalid function argument

on catalog.tf line 11, in resource "aws_glue_crawler" "bucket_crawlers":
11: for_each = {for key, value in setproduct(local.bucket-names, module.crawler_source_buckets.id): key=>value}
├────────────────
│ while calling setproduct(sets...)
│ module.crawler_source_buckets.id is a object

Invalid value for "sets" parameter: a set or a list is required.

写法2:

for_each = {for key, value in setproduct(local.bucket-names, module.crawler_source_buckets.*.id): key=>value}

写法3:

for_each = {for key, value in setproduct(local.bucket-names, module.crawler_source_buckets.[*].id): key=>value}

其中一种报错:

Error: Invalid template interpolation value

on catalog.tf line 14, in resource "aws_glue_crawler" "bucket_crawlers":
14: path = "s3://${each.value[1]}"
├────────────────
│ each.value[1] is object with 2 attributes

Cannot include the given value in a string template: string required.

错误原因

用for_each实例化的模块,module.crawler_source_buckets本质是一个映射(Map),键是local.bucket-names里的桶名,值是每个模块实例的输出对象。之前的写法错误在于:

  1. 直接访问module.crawler_source_buckets.id会返回一个键值对Map,而非setproduct所需的列表/集合
  2. *.id和.[*].id是针对count创建资源的语法,不适用于for_each创建的模块
  3. 用setproduct会生成桶名和桶ID的笛卡尔积,完全没必要(每个桶名对应唯一桶ID),反而会导致资源重复或类型错误

正确实现方案

因为模块实例的键就是桶名,直接遍历module.crawler_source_buckets即可,无需额外的setproduct或列表转换:

修改后的catalog.tf

resource "aws_glue_catalog_database" "catalog_databases" {
  for_each = module.crawler_source_buckets
  name     = each.key
}

resource "aws_glue_crawler" "bucket_crawlers" {
  for_each      = module.crawler_source_buckets
  database_name = each.key
  name          = "${each.key}-crawler"
  role          = aws_iam_role.glue_crawler_role.arn

  s3_target {
    path = "s3://${each.value.id}"
  }
  schedule = "cron(*/15 * * * ? *)"
}

关键说明

  • each.key:对应模块实例的键,也就是桶名,直接用来作为数据库名和爬虫名称的前缀
  • each.value.id:对应每个模块实例输出的桶ID(即桶名),直接拼接成S3路径
  • 这种写法完全对齐模块的实例数量,自动同步桶的增删,无需维护额外的列表

补充:如果需要提取模块输出的列表

如果确实需要把模块的输出转换成列表(比如其他场景),可以用values()函数:

# 获取所有桶ID的列表
locals {
  bucket_ids = [for bucket in values(module.crawler_source_buckets) : bucket.id]
}

内容的提问来源于stack exchange,提问作者AlexLordThorsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 08:15:35