Use Terraform module to manage GCP Pub/Sub service

Create a Terraform module to create GCP pubsub resources, including topics, subscriptions and iam permissions.

Terraform code

First define a Terraform variable pubsub_config to store your Pub/Sub configuration, then extract your subscriptions to a local variable.

The Terraform code is placed here

# Define a variable to store pubsub configuration
variable "pubsub_config" {
  type = map(object({
    subscriptions = list(object({
      name        = string
      subscribers = list(string)
    }))
    publishers    = list(string)
  }))
  description = "Pub/Sub configuration, use topics name as key"
}

locals {
  subscriptions = flatten([
    for topic, config in var.pubsub_config : [
      for sub in config.subscriptions : {
        topic       = topic
        name        = sub.name
        subscribers = sub.subscribers
      } if length(config.subscriptions) > 0
    ]
  ])
}

# Create Pub/Sub Topics
resource "google_pubsub_topic" "topics" {
  for_each = var.pubsub_config
  name     = each.key
  project  = var.project_id

  # message retention policy, keep for 7 days
  message_retention_duration = "604800s"

}

# Create subscriptions for every topics
resource "google_pubsub_subscription" "subscriptions" {
  for_each = tomap({
    for subscription in local.subscriptions : "${subscription.topic}-${subscription.name}-subscription" => {
      name  = subscription.name
      topic = subscription.topic
    }
  })

  name    = each.value.name
  topic   = google_pubsub_topic.topics[each.value.topic].name
  project = var.project_id

  ack_deadline_seconds = 600
}

# Grant Topic Publisher role to GSA
resource "google_pubsub_topic_iam_binding" "publishers" {
  for_each = {
    for topic, config in var.pubsub_config :
    "${topic}-publisher" => {
      topic   = topic
      members = config.publishers
    } if length(config.publishers) > 0
  }

  topic   = google_pubsub_topic.topics[each.value.topic].name
  project = var.project_id

  role    = "roles/pubsub.publisher"
  members = [for sa in each.value.members : "serviceAccount:${sa}"]
}

# Grant subscriber role to every subscriptions in topics
resource "google_pubsub_subscription_iam_binding" "subscribers" {
  for_each = tomap({
    for subscription in local.subscriptions : "${subscription.topic}-${subscription.name}-subscriber" => {
      name    = subscription.name
      topic   = subscription.topic
      members = subscription.subscribers
    }
  })

  subscription = google_pubsub_subscription.subscriptions["${each.value.topic}-${each.value.name}-subscription"].name
  project      = var.project_id

  role    = "roles/pubsub.subscriber"
  members = [for sa in each.value.members : "serviceAccount:${sa}"]
}

terraform.tfvars

pubsub_config = {
  "order-events" = {
    subscriptions = [
      {
        name        = "order-processor",
        subscribers = ["[email protected]"]
      },
      {
        name        = "order-archive",
        subscribers = ["[email protected]"]
      }
    ],
    publishers = ["[email protected]"]
  },
  "payment-events" = {
    subscriptions = [
      {
        name        = "payment-notifications",
        subscribers = ["[email protected]"]
      }
    ],
    publishers = ["[email protected]"]
  }
}
Tags: gcloud
Share: X (Twitter) Facebook LinkedIn