Call a terraform variable from a different directory

Hi,
I am new to Terraform and I am creating infrastructure in Azure using Terraform. I have a variables file in my root folder and I have my create vnet script in another directory. My directory looks like:

enter image description here

My main.tf and variables.tf are in the root directory PaaS. My CreateVnets.tf is in my CreateVnets directory. It works fine if I put the variables file in the CreateVnets directory, then I just call the variables by using the var.variablename call. But we are going to have a number of different directories to create different Terraform resources so I want to use one variables file.

How do I access my variables in variables.tf in my Vnets.tf file.

So for example my location variable in variables.tf:

variable "LOCATION" {
  type = string
  default = "West Europe"
}

How do I call that variable in my Vnets.tf where I create my Azure resources?

Hi @mikepower79,

Each module’s input variables are independent from the others. Input variables are approximately analogous to the parameters to a function in a general-purpose language, where each function defines its own set of parameters and the caller passes in suitable values for each one.

If all of your modules will use a variable called location then you’d need to declare it in each module, but then in the calling module you can pass it down from the root so that the actual value of the variable is still declared in only one place:

variable "location" {
  type    = string
  default = "West Europe"
}

module "firewall" {
  source = "./AzureFirewall"

  location = var.location
}

module "vnets" {
  source = "./Vnets"

  location = var.location
}

If you have several arguments that are needed by most of or all of your shared modules then you can reduce the boilerplate by defining them all as a single variable of an object type and then passing them all in together as a single value:

variable "location" {
  type    = string
  default = "West Europe"
}

variable "other_example" {
  type = string
}

locals {
  common = {
    location      = var.location
    other_example = var.other_example
  }
}

module "firewall" {
  source = "./AzureFirewall"

  common = local.common
}

module "vnets" {
  source = "./Vnets"

  common = local.common
}

Inside each of the modules, you can declare the parts of common that each module needs by declaring an object type constraint:

variable "common" {
  type = object({
    # If a particular module doesn't need one of
    # the attributes then you can omit it. This
    # type constraint calls for _at least_ these
    # two attributes, and will discard any others.
    location      = string
    other_example = string
  })
}

Inside the individual modules you can access e.g. var.common.location to get the location from the common object.

This sort of design keeps your modules somewhat independent from one another so that they can evolve separately over time. If you don’t yet need a separate namespace for each of these components then it may be better to keep all of your resources inside a single module, perhaps using different .tf files to represent different components, and wait to decompose until there are some clearer architectural boundaries between your components (which often leads to them sharing relatively little, because each one is focused on only one need at a time).

1 Like

Thats great. Thanks for the very detailed response.

A post was split to a new topic: Need a way to share variable definitions between configurations