Pass a variable in module input

I am trying to pass a variable inside module output as input like below and it was not working.

port = element(module.rds_aurora_cluster_"${var.envname}".db_port, 0)

Error: A comma is required to separate each function argument from the next.

it works fine if I pass the actual value like below.

port = element(module.rds_aurora_cluster_dev.db_port, 0),

But I need that “dev” to be an environment variable.

Hi @dhineshbabuelango,

Module names in Terraform are static, and so are references to them. There is no way to dynamically choose a module block to refer to.

There are some other approaches that you can use instead, though:

  • One way would be for you to write your configuration to support only a single environment at a time, and then use multiple Terraform Cloud workspaces referring to that single configuration where each has a different configured value of this envname variable. You will then only have one module "rds_aurora_cluster" block, rather than one per environment, because the duplication of that per environment will be represented by there being one workspace per environment.

    You’d refer to its outputs just as module.rds_aurora_cluster.db_port in that case, because the module name need not include the environment name when the configuration only represents one environment.

    This also means you’ll be able to plan and apply each environment separately, which is a typical goal for many Terraform users so that e.g. they can try new changes out on a development environment first, before applying them to production.

  • If you do want all of these in a single module, and the differences between your environments are systematic, you can write a single module "rds_aurora_cluster" block which has for_each set to a local value that represents all of your environments:

    locals {
      environments = {
        dev  = {}
        prod = {}
    module "rds_aurora_cluster" {
      for_each = local.environments
      # ...

    This tells Terraform to create multiple instances of that module, each identified by one of the keys in local.environments. That means that module.rds_aurora_cluster elsewhere in the module will be a map of objects, and so you can refer to particular environments via a dynamic index expression:

    • module.rds_aurora_cluster["dev"].db_port
    • module.rds_aurora_cluster[var.envname].db_port
  • Finally, if you need all of the environments represented in a single configuration but their configurations for this module are not systematic enough to use with for_each, you can write out multiple separate module blocks and then construct yourself a map of objects similar to the one Terraform would make automatically in the for_each case:

    module "rds_aurora_cluster_dev" {
      # ...
    module "rds_aurora_cluster_prod" {
      # ...
    locals {
      rds_aurora_clusters = {
        dev  = module.rds_aurora_cluster_dev
        prod = module.rds_aurora_cluster_prod

    Now each of the module blocks is just a single object again as in your current configuration, but local.rds_aurora_clusters is a mapping that you can index with dynamic keys similar to my previous bullet point:

    • local.rds_aurora_clusters["dev"].db_port
    • local.rds_aurora_clusters[var.envname].db_port

Which of these approaches to choose will depend on the details of what you are trying to represent, so I can’t recommend any in particular though I can say that the first one is the most common choice for situations involving multiple environments where the goal is for changes to be rolled out gradually across one environment at a time, because separate workspaces can be planned and applied separately.

This worked, thanks a lot :slightly_smiling_face: