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

使用timestamp()的Terraform for_each无法执行plan的解决方法

问题解决:Terraform for_each 依赖 timestamp() 导致计划阶段报错

错误原因

Terraform 的 for_each 要求在计划(plan)阶段就能明确集合的元素数量和每个元素的唯一标识,而 timestamp() 属于「应用(apply)阶段函数」——它的实际值只有在执行 apply 操作时才能确定,这直接导致 local.alert_policies_ext_vars 的内容在 plan 阶段无法固定,Terraform 无法提前预判要创建多少个 null_resource.test 实例,因此抛出错误。

解决方案

根据实际需求,有以下几种可行的处理方式:

方式一:将时间判断移至 Provisioner 内部

保持 for_each 遍历固定的策略组集合,把时间筛选逻辑放到 local-exec 中,仅在 apply 阶段执行符合时间条件的操作:

resource "null_resource" "test" {
  # 遍历固定的alert_policies_groups,plan阶段可确定实例数量
  for_each = { for idx, group in local.alert_policies_groups : idx => group }

  provisioner "local-exec" {
    interpreter = ["bash", "-c"]
    command = <<EOT
      CURRENT_DAY="${formatdate("EEEE", timestamp())}"
      # 判断当前日期是否在当前组的timeslot范围内
      if [[ " ${join(" ", each.value.timeslot)} " =~ " \$CURRENT_DAY " ]]; then
        echo "Processing policy group: ${jsonencode(each.value)}"
      fi
    EOT
  }
}

方式二:用静态变量传入目标日期

如果可以接受基于「计划执行时的日期」而非「应用执行时的日期」筛选,可将目标日期定义为变量,让其在 plan 阶段即可确定值:

# 定义变量,可手动指定目标日期,默认值为计划执行时的日期
variable "target_day" {
  type    = string
  default = formatdate("EEEE", timestamp())
}

locals {
  alert_policies_groups = [
    {
      version  = "v2"
      timeslot = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
    },
    {
      version  = "v2"
      timeslot = ["Saturday", "Sunday"]
    },
  ]

  # 基于变量筛选,plan阶段即可确定结果集合
  alert_policies_ext_vars = distinct(flatten([
    for key, value in local.alert_policies_groups : [
      merge(value, { timeslot = null })
    ] if contains(value.timeslot, var.target_day)
  ]))
}

resource "null_resource" "test" {
  # 用map形式遍历,避免列表索引变动导致资源重建
  for_each = { for idx, group in local.alert_policies_ext_vars : idx => group }

  provisioner "local-exec" {
    command = "echo ${jsonencode(each.value)}"
  }
}

执行 plan 时可手动指定日期:

terraform plan -var target_day="Saturday"

方式三:外部脚本提前确定筛选条件

如果必须基于「apply 时的准确时间」动态创建资源,可通过外部脚本提前计算目标日期,生成 Terraform 变量文件后再执行操作:

  1. 编写 shell 脚本(比如 prepare.sh):
#!/bin/bash
# 获取当前日期(apply时的日期)
TARGET_DAY=$(date +%A)
# 生成terraform.tfvars文件
cat > terraform.tfvars <<EOF
target_day = "$TARGET_DAY"
EOF
# 执行Terraform
terraform apply
  1. 修改 Terraform 代码,读取变量文件中的 target_day 进行筛选(同方式二的变量定义和本地逻辑)。

额外注意点

原代码中 local.alert_policies_ext_vars[0] 的写法存在问题:当使用 for_each 时,应通过 each.value 访问当前实例对应的元素,而非固定索引 0,否则所有实例都会输出同一个元素的值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:13:45