Terraform执行plan报错:for_each参数需为映射或字符串集合
Terraform for_each 参数错误解决(S3桶KMS密钥配置场景)
错误信息
│ Error: Invalid for_each argument
│
│ on ../ec2-pattern/main.tf line 39, in module "s3_bucket":
│ 329: for_each = local.s3_bucket_list
│ ├────────────────
│ │ local.s3_bucket_list is tuple with 1 element
│
│ The given "for_each" argument value is unsuitable: the "for_each" argument
│ must be a map, or set of strings, and you have provided a value of type tuple.
问题根源
- 类型不匹配:
local.s3_bucket_list通过flatten生成了元组(tuple)类型,但for_each要求参数必须是映射(map)或字符串集合(set(string))。 - KMS密钥赋值逻辑错误:
merge中重复设置kms_master_key_id,后赋值的内容会直接覆盖前面的,导致用户自定义密钥的逻辑失效。
修正方案
1. 修正本地变量,生成Map结构
将local.s3_bucket_list改为Map类型,保留原桶配置的键名,同时正确处理KMS密钥的优先级:
locals { s3_bucket_map = { for k, v in var.s3_buckets : k => merge(v, { # 优先使用用户提供的KMS密钥,未提供则使用自动查找的密钥 kms_master_key_id = coalesce(lookup(v, "kms_master_key_id", null), module.datasource-module.data.s3_kms.arn_alias) }) } }
2. 调整Module的for_each参数
将for_each指向修正后的Map类型本地变量:
module "s3_bucket" { for_each = local.s3_bucket_map create_bucket = each.value.create_bucket policy_bucket_read_arns_csv = each.value.policy_bucket_read_arns_csv policy_bucket_modify_arns_csv = each.value.policy_bucket_modify_arns_csv kms_master_key_id = each.value.kms_master_key_id }
3. 优化变量类型定义(可选但推荐)
给s3_buckets变量指定明确的类型约束,提升代码可读性和类型检查能力:
variable "s3_buckets" { description = "所有S3桶的配置映射" type = map(object({ policy_bucket_modify_arns_csv = string policy_bucket_read_arns_csv = string bucket_suffix = string contains_pci_info = bool create_bucket = optional(bool, true) # 可选参数,默认创建桶 kms_master_key_id = optional(string) # 可选参数,用户可自定义KMS密钥 })) default = {} }
说明
coalesce函数会返回第一个非空值,完美实现"用户提供则用用户的,否则用自动查找的"逻辑。- 保持Map结构的
local.s3_bucket_map,既能满足for_each的类型要求,又能保留原桶配置的键名作为资源实例的唯一标识,避免Terraform重新创建资源。
内容的提问来源于stack exchange,提问作者dmart
相关产品推荐
相关产品推荐

