Variables inside map declaration

Hi,

First off - apologies - I’m extremely new (3 hours in!) to using terraform.

I am looking to try and use the value of a variable inside the declaration of another variable.

Below is my code - what am I doing wrong?

variables.tf:

variable "EnvironmentName" {
    type = "string"
}
variable "tags" {
    type = "map"
    default = {
        Environment = "${var.EnvironmentName}"
        CostCentre = "C1234"
        Project = "TerraformTest"
        Department = "Systems"
    }
}

Variables-dev.tfvars:

EnvShortName = "Dev"
EnvironmentName = "Development1"
#Location
Location = "westeurope"

main.tf:

resource “azurerm_resource_group” “TestAppRG” {
name = “EUW-RGs-${var.EnvShortName}”
location = “${var.Location}”
tags = “${var.tags}”
}

I am getting the following error:

Error: Variables not allowed
on variables.tf line 18, in variable “tags”:
18: Environment = “${var.EnvironmentName}”
Variables may not be used here.

I understand that the error message is fairly self explanatory and it is probably my approach that is wrong - but how do I use a variable in the definition of another variable map? is this even possible?

I will be standing up multiple resources - so want the tags to be built as a map and be passed into each resource - but I also want to recycle the map with other tfvars files to deploy multiple instances for different teams to work on.

Hi @Fazer1987!

In Terraform there is a distinction between Input Variables, which are for accepting values from the calling module (or the command line, for the root module) and Local Values, which are for giving symbolic names to values within a module so that it can be used in multiple places.

Input variable default values must be constant, but in this case it looks like your tags map would be a good use-case for local values instead:

variable "environment_name" {
  type = string
}

variable "extra_tags" {
  type    = map(string)
  default = {}

  description = "Extra tags to be included when tagging objects, in addition to the ones provided automatically by this module."
}

locals {
  tags = merge(
    var.extra_tags,
    {
      Environment = var.environment_name
      CostCentre  = "C1234"
      Project     = "TerraformTest"
      Department  = "Systems"
    },
  )
}

Elsewhere in the configuration you can use local.tags to refer to that constructed final tags map, which is built by merging together values from other locations. You could make those CostCentre, Project, and Department tags also settable as input variables if that would be appropriate in a given situation, or you can mix settable vs. hard-coded values as in your example.

resource “azurerm_resource_group” “test_app” {
  # ...

  tags = local.tags
}

Note that idiomatic Terraform style is for Terraform-oriented identifiers to be written all in lowercase with underscores, not in “title case”. Terraform will accept either, but I’ve used the idiomatic naming style in the examples above.

2 Likes

Wow… its really that simple? I’ve obviously been massively overthinking this.

Thankyou so much. Also, point noted regarding the casing of names etc - I’ll be sure to (try and) remember that :slight_smile:

Thanks again for your quick help and apologies in advance if I end up pestering your forums a lot while I’m getting my head round this.

1 Like

@Fazer1987 - I went through the same realization process (local values vs input variables).

We hope the forums are a place for all kinds of discovery and discussion.

Glad you’re here.