How to DRY up these modules?

Is there a way to DRY up these modules? Thanks

module "app" {
  source = "./imaged"
  node_group = "app"
  name_prefix = "app"
  name_suffix = var.name_suffix
  project = var.project
  zone = var.zone
  source_disk_name = var.source_disk_name
  source_image_name = var.source_image_name
  machine_type = var.app_machine_type
}

module "pgbouncer" {
  source = "./imaged"
  node_group = "pgbouncer"
  name_prefix = "pgbouncer"
  name_suffix = var.name_suffix
  project = var.project
  zone = var.zone
  source_disk_name = var.source_disk_name
  source_image_name = var.source_image_name
  machine_type = var.pgbouncer_machine_type
}

module "sidekiq" {
  source = "./imaged"
  node_group = "sidekiq"
  name_prefix = "sidekiq"
  name_suffix = var.name_suffix
  project = var.project
  zone = var.zone
  source_disk_name = var.source_disk_name
  source_image_name = var.source_image_name
  machine_type = var.sidekiq_machine_type
}

Yes but it’s not very nice…

You can change the module to take all or most of its parameters as a single variable of object type, e.g. just called parameters, and then you can pass in a common object, probably defined in terms of a local variable, to each module instance.

Of just use a single module block with for_each?

Can you give a quick example of how you would do that? I’m not sure if there’s a way to do it for a root module. This doesn’t work and complains that name is not a valid attribute

module "imaged" {
  for_each = {
    app = {
      node_group = "app"
      machine_type = var.app_machine_type
    }
    pgbouncer-app = {
      node_group = "pgbouncer"
      machine_type = var.pgbouncer_machine_type
    }
  }

  # This will be the name of the module
  name = each.key

  source = "./imaged"
  node_group = each.value.node_group
  name_prefix = each.key
  name_suffix = var.name_suffix
  project = var.project
  zone = var.zone
  source_disk_name = var.source_disk_name
  source_image_name = var.source_image_name
  nomad_running_healthcheck_name = var.nomad_running_healthcheck_name
  machine_type = each.value.machine_type
}

There is no such thing as a special “name” attribute, so it is complaining because the module doesn’t allow for one.

From your example code the module would be called module.imaged['app'] and module.images['pgbouncer-app'].

Ah ok gotcha, is there any way to get module.app and module.pgbouncer-app references instead and still be able to DRY it up like this?

No. If you use for_each or count within a module or resource you have the single name with a [] suffix (string values for for_each and numbers for count).

Choosing your own resource/module name individually is only possible by having multiple blocks.

1 Like