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

在Terraform中使用for_each引用GCP Pub/Sub Topic资源名称

问题描述

团队使用Terraform部署GCP资源,已有两个Pub/Sub Topic定义在dead_letter_topics.tf文件中:

# dead_letter_topcs.tf
resource "google_pubsub_topic" "primary_dead_letter" {
  name = "primary-dead-letter"
  labels = {
      role  = "dead-letter"
      qname = "primary"
  }
  message_retention_duration = "1209600s"
}

resource "google_pubsub_topic" "secondary_dead_letter" {
  name = "secondary-dead-letter"
  labels = {
      role  = "dead-letter"
      qname = "secondary"
  }
  message_retention_duration = "1209600s"
}

为避免重复编写订阅资源,尝试在my_deadletter_subscriptions.tf中用for_each批量创建订阅:

# my_deadletter_subscriptions.tf
locals {
  queue_names = toset(["primary", "secondary"])
}

resource "google_pubsub_subscription" "deadletter_gcs" {
  for_each = local.queue_names

  name  = "deadletter-gcs-${each.key}"
  topic = "google_pubsub_topic.${each.key}_dead_letter.name"

  enable_message_ordering      = false
  enable_exactly_once_delivery = false

  cloud_storage_config {
   ... more ...
  }
}

执行时触发错误:

Error: Error creating Subscription: googleapi: Error 400: Invalid resource name given (name=projects/mygcpproject/topics/google_pubsub_topic.primary_dead_letter.name).
Refer to Pub/Sub资源命名规范了解更多信息。

需要实现:不重复编写订阅资源,通过queue_names变量正确引用已创建的Topic名称。

解决方案

问题根源

你直接将字符串"google_pubsub_topic.${each.key}_dead_letter.name"赋值给topic参数,Terraform没有将其解析为资源引用,而是直接把这个字符串作为Topic名称传递给GCP,导致GCP识别到无效的资源路径。

正确实现方式

方式1:通过资源映射动态引用(推荐)

建立队列名到Topic资源的映射,直接引用资源的id属性(GCP要求的完整资源路径):

# my_deadletter_subscriptions.tf
locals {
  queue_names = toset(["primary", "secondary"])
  # 映射队列名到对应的Topic资源
  topic_map = {
    primary   = google_pubsub_topic.primary_dead_letter
    secondary = google_pubsub_topic.secondary_dead_letter
  }
}

resource "google_pubsub_subscription" "deadletter_gcs" {
  for_each = local.queue_names

  name  = "deadletter-gcs-${each.key}"
  # 引用对应Topic的完整资源ID
  topic = local.topic_map[each.key].id

  enable_message_ordering      = false
  enable_exactly_once_delivery = false

  cloud_storage_config {
   ... more ...
  }
}

这种方式直接关联Terraform资源,后续如果Topic的名称或路径变化,订阅代码会自动同步,无需手动修改。

方式2:按命名规则拼接Topic路径(不推荐)

如果Topic的命名规则固定(比如[queue-name]-dead-letter),可以手动拼接完整资源路径,但这种方式硬编码规则,灵活性差:

# 需要提前定义gcp_project_id变量
topic = "projects/${var.gcp_project_id}/topics/${each.key}-dead-letter"

后续扩展优化

如果后续要新增更多Topic,且资源名称始终遵循${queue-name}_dead_letter的格式,可以优化topic_map的生成逻辑,避免手动维护映射关系:

locals {
  queue_names = toset(["primary", "secondary", "tertiary"])
  # 自动生成队列名到Topic资源的映射
  topic_map = {
    for qname in local.queue_names : qname => lookup(google_pubsub_topic, "${qname}_dead_letter")
  }
}

这样只要在queue_names中新增队列名,同时在dead_letter_topics.tf中创建对应的google_pubsub_topic.${qname}_dead_letter资源,订阅就会自动生成。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:33:17