Terraform 因 for_each 参数无效而失败/“for_each”参数必须是地图或字符串集

问题描述 投票:0回答:1

运行 terraform plan 时出现以下错误: 给定的“for_each”参数值不合适:“for_each”参数必须是映射或字符串集,并且您提供了元组类型的值。

我正在尝试创建存储桶,但要么允许用户提供 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.
dev.tfvars

s3_buckets = {
  bucket1 : {

    policy_bucket_modify_arns_csv = "s3-policy-arns/s3-policy-modify-arns.csv"
    policy_bucket_read_arns_csv   = "s3-policy-arns/s3-policy-read-arns.csv"
    bucket_suffix                 = "test"
    contains_pci_info             = false
  }
}

main.tf

locals {
  s3_bucket_list = flatten([
    for k, v in var.s3_buckets :
    merge(v, { kms_master_key_id = lookup(v, "kms_master_key_id", null), kms_master_key_id = module.datasource-module.data.s3_kms.arn_alias })

  ])
}

module "s3_bucket" {

  for_each = local.s3_bucket_list

  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
}

variable "s3_buckets" {
  description = "A map of all buckets"
  type        = any
  default     = {}
}
foreach terraform
1个回答
0
投票

错误似乎很明显:

给定的“for_each”参数值不合适...必须是映射或字符串集,并且您提供了元组类型的值...

要解决类似问题,您必须输出您的

s3_bucket_list
,以便您可以确认是正确的类型,在您的输出是列表的情况下,您正在做的
flatten([
仅适用于列表:
https://developer.hashicorp.com/terraform/language/functions/flatten

这是我更改您的代码的方法:

variable "s3_buckets" {
  default = {
    bucket1 : {
      bucket_suffix     = "test"
      contains_pci_info = false
    }
    bucket2 : {
      bucket_suffix     = "abc"
      contains_pci_info = true
      kms_master_key_id = "123"
    }
  }
}

locals {
  s3_bucket_list = {
    for k, v in var.s3_buckets :
    k => merge(v, { kms_master_key_id = lookup(v, "kms_master_key_id", "foo") })
  }
}

output "s3_bucket_list" {
  value = local.s3_bucket_list
}

如果您对此进行地形计划,我们会得到

Changes to Outputs:
  + s3_bucket_list = {
      + bucket1 = {
          + bucket_suffix     = "test"
          + contains_pci_info = false
          + kms_master_key_id = "foo"
        }
      + bucket2 = {
          + bucket_suffix     = "abc"
          + contains_pci_info = true
          + kms_master_key_id = "123"
        }
    }

这是我们可以在

for_each
中使用的正确地图...... 我改变的事情:

  • 向变量 s3_buckets 添加了一个元素以显示更好的输出
  • 删除
    flatten
    ,你的结构是扁平的,不知道为什么你需要它
  • lookup
    中,我更改了
    foo
    的空值,您可以在那里放置任何您想要的默认值,就像您拥有的那样
    module.datasource-module.data.s3_kms.arn_alias
  • 在循环的返回中,现在我们执行
    k => ...
    创建映射结构

我希望这足够清楚。

© www.soinside.com 2019 - 2024. All rights reserved.