FAQ | This is a LIVE service | Changelog

Skip to content

Plans with module fail if `topic_id` is not statically known

We are seeing plans with the following:


│ Error: Invalid count argument

│   on /terraform_data/modules/msteams_workflow_notifications/main.tf line 4, in resource "random_id" "topic_name":
│    4:   count = var.topic_id == null ? 1 : 0

│ The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that
│ the count depends on.

This is due to the following use in monitoring.tf in gcp-product-factory:

module "msteams_workflow_notifications" {
  source  = "gitlab.developers.cam.ac.uk/uis/gcp-pubsub-to-ms-teams/devops"
  version = "~> 1.2"
  project = local.meta_project_id
  region  = var.region

  msteams_channel_webhook_urls = var.msteams_channel_webhook_urls
  topic_id                     = google_pubsub_topic.default_monitoring.id
}

The problem here is that, until google_pubsub_topic.default_monitoring is created, terraform cannot know what the value of google_pubsub_topic.default_monitoring.id is and so it doesn't know whether to plan to create the google_pubsub_topic.default resource within this module.

Having resources whose existence depends on the value of arguments is a common problem with terraform modules and the usual pattern is to have an explicit "create" flag. Confer the create_... arguments in the Google Load Balancer module. This allows the user of the module to signal that they expect something to be provided before the value is known.

So, for this module:

  1. Add a create_default_topic variable, which defaults to true and update the resources in main.tf:
    resource "random_id" "topic_name" {
      count = var.create_default_topic ? 1 : 0
    
      byte_length = 4
      prefix      = "pubsub2teams-"
      keepers     = {}
    }
    
    resource "google_pubsub_topic" "default" {
      count = var.create_default_topic ? 1 : 0
    
      project = var.project
      name    = random_id.topic_name[0].hex
    }
  2. Keep the definition of local.topic_id the same as it is.

The effect of specifying the topic_id as above now "fails safe" in that a redundant MS Teams topic is created. Users of the module can then update call sites. For the motivating example:

module "msteams_workflow_notifications" {
  source  = "gitlab.developers.cam.ac.uk/uis/gcp-pubsub-to-ms-teams/devops"
  version = "~> 1.2"
  project = local.meta_project_id
  region  = var.region

  msteams_channel_webhook_urls = var.msteams_channel_webhook_urls
  create_default_topic         = false
  topic_id                     = google_pubsub_topic.default_monitoring.id
}

The use of an explicit create_default_topic = false allows the user of the module to indicate that it intends to provide topic_id but allows the plan to proceed if google_pubsub_topic.default_monitoring has not yet been created.