loop across modules in terraform

San*_* P. 0 terraform terraform-provider-gcp

I need to build about 30 pub sub topics in GCP, creating each module for a pub sub topic is a tedious process, is there any better way for handling it ?

module "a" {
  source       = ""
  project_id   = var.project_id
  topic        = var.a["topic_name"]
  topic_labels = var.a["topic_labels"]
  pull_subscriptions = [
    {
      name                    = var.a["pull_subscription_name"]
      ack_deadline_seconds    = var.a["ack_deadline_seconds"]
      max_delivery_attempts   = var.a["max_delivery_attempts"]
      maximum_backoff         = var.maximum_backoff
      minimum_backoff         = var.minimum_backoff
      expiration_policy       = var.expiration_policy
      enable_message_ordering = true
    }
  ]
}

module "b" {
  source       = ""
  project_id   = var.project_id
  topic        = var.b["topic_name"]
  topic_labels = var.b["topic_labels"]
  pull_subscriptions = [
    {
      name                    = var.b["pull_subscription_name"]
      ack_deadline_seconds    = var.b["ack_deadline_seconds"]
      max_delivery_attempts   = var.b["max_delivery_attempts"]
      maximum_backoff         = var.maximum_backoff
      minimum_backoff         = var.minimum_backoff
      expiration_policy       = var.expiration_policy
      enable_message_ordering = true
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

In tfvars passing the values to the above modules like below:

a = {
  topic_name             = "abc"
  topic_labels           = { env : "prod", purpose : "a" }
  pull_subscription_name = "abc-sub"
  ack_deadline_seconds   = 600
  max_delivery_attempts  = 3
}

b = {
  topic_name             = "bcd"
  topic_labels           = { env : "prod", purpose : "b" }
  pull_subscription_name = "bcd-sub"
  ack_deadline_seconds   = 600
  max_delivery_attempts  = 3
}
Run Code Online (Sandbox Code Playgroud)

Can we somehow combine the variables in tfvars and pass in to a single module ?

I also wanna know the best practise to maintain the above terraform script to keep them individually or utilise one module to created 50 topics ?

Thank You !

Mar*_*ins 5

对于两个单独的变量,您的选择有点有限,因为 Terraform 无法将这两个单独的变量视为以系统方式连接。(每个变量与 Terraform 中的其他对象一样,从依赖关系解析的角度来看是完全独立的。)

但是,如果您可以将其重组为映射类型的单个变量,那么您可以使用资源for_each系统地为映射的每个元素声明一个实例:

variable "topics" {
  type = map(object({
    labels                 = map(string)
    pull_subscription_name = string
    ack_deadline_seconds   = number
    max_delivery_attempts  = number
  }))
}

module "topic" {
  source   = "..."
  for_each = var.topics

  project_id   = var.project_id
  topic        = each.key
  topic_labels = each.value.labels
  pull_subscriptions = [
    {
      name                    = each.value.pull_scription_name
      ack_deadline_seconds    = each.value.ack_deadline_seconds
      max_delivery_attempts   = each.value.max_delivery_attempts
      maximum_backoff         = var.maximum_backoff
      minimum_backoff         = var.minimum_backoff
      expiration_policy       = var.expiration_policy
      enable_message_ordering = true
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

对于此示例,我假设您的topic_name属性将是实例的合适唯一键,因此我将其从声明的对象类型中删除,目的是将其放入映射键中。换句话说,该topics变量的值应如下所示:

topics = {
  abc = {
    labels                 = { env = "prod", purpose = "a" }
    pull_subscription_name = "abc-sub"
    ack_deadline_seconds   = 600
    max_delivery_attempts  = 3
  }
  bcd = {
    labels                 = { env = "prod", purpose = "b" }
    pull_subscription_name = "bcd-sub"
    ack_deadline_seconds   = 600
    max_delivery_attempts  = 3
  }
}
Run Code Online (Sandbox Code Playgroud)

由此,Terraform 将了解您打算使用以下地址声明模块实例:

  • module.topic["abc"]
  • module.topic["bcd"]

由于主题名称是地址的一部分,Terraform 可以识别编辑现有主题对象(不更改其名称)与在地图中添加/删除主题之间的区别,并将其转换为具有模块内声明的资源实例的相应计划。

如果您能够更改远程系统知道的主题名称,而Terraform理解作为单独的删除和创建操作,那么您可以将其恢复name为该对象类型的属性,然后进行设置topic = each.value.name,然后映射键将用于在 Terraform 中进行跟踪,并且在远程系统中根本不可见。