Posted on 10 Comments

Pass variables values inside terraform modules

In this article I will explain two different ways to pass variables values inside terraform modules. Modules let you separate your code into small units and help the engineer structure its project better.

https://www.terraform.io/language/modules/syntax

Modules in terraform (terraform files) can be placed on folders and their location should be provided on the module directive. Lets say for example that you host a main.tf on your current working directory which should call two modules. The first module would be a storage account and the second would be an app service. Your main.tf file should look like below.

module "app_service_test" {
  source                  = "./modules/appservice"
}
module "storage_account_test" {
  source                  = "./modules/storageaccount"
}

However you want to pass some variables inside the child modules for example the resource group name, location etc.

First method – Define variables on root module

The first way you can pass variables inside your child modules would be to define a variables.tf file on your main module and a terraform.tfvars. Then you should also define a variables.tf file inside each module and contain the definition of each module.

terraform.tfvars (root module)

app_service_plan_name   = "ger-plan-test"
app_service_name        = "ger-site-test"
resource_group_name     = "geralexgr-terraform-rg"
resource_group_location = "West Europe"
storage_account_name    = "geralexgrsgv2"

variables.tf (root module)

variable "storage_account_name" {
  type        = string
  description = "Storage account name"
  default     = ""
}

variable "resource_group_name" {
  type        = string
  description = "RG name in Azure"
}

variable "app_service_plan_name" {
  type        = string
  description = "App Service Plan name in Azure"
}

variable "app_service_name" {
  type        = string
  description = "Name for the app service"
}

variable "resource_group_location" {
  type        = string
  description = "RG location in Azure"
}

variables.tf (storageaccount module)

variable "storage_account_name" {
    type        = string
    description = "Storage account name"
}
variable "resource_group_name" {
    type        = string
    description = "RG name in Azure"
}

variable "resource_group_location" {
    type        = string
    description = "RG location in Azure"
}

variables.tf (appservice module)

variable "app_service_plan_name" {
    type        = string
    description = "App Service Plan name in Azure"
}

variable "app_service_name" {
    type = string
    description = "Name for the app service"
}
variable "resource_group_name" {
    type        = string
    description = "RG name in Azure"
}

variable "resource_group_location" {
    type        = string
    description = "RG location in Azure"
}

Then on your main module you should call your child modules as follows:

module "app_service_test" {
  source                  = "./modules/appservice"
  app_service_plan_name   = var.app_service_plan_name
  app_service_name        = var.app_service_name
  resource_group_name     = var.resource_group_name
  resource_group_location = var.resource_group_location
}

module "storage_account_test" {
  source                  = "./modules/storageaccount"
  storage_account_name    = var.storage_account_name
  resource_group_name     = var.resource_group_name
  resource_group_location = var.resource_group_location
}

Second method – Pass variables on module call

With this approach you do not need to have variables.tf file and terraform.tfvars file inside your root module. You only need the definition as described above inside appservice and storageaccount folders (variables.tf).

variables.tf (appservice module)

variable "app_service_plan_name" {
    type        = string
    description = "App Service Plan name in Azure"
}

variable "app_service_name" {
    type = string
    description = "Name for the app service"
}
variable "resource_group_name" {
    type        = string
    description = "RG name in Azure"
}

variable "resource_group_location" {
    type        = string
    description = "RG location in Azure"
}

variables.tf (storageaccount module)

variable "storage_account_name" {
    type        = string
    description = "Storage account name"
}
variable "resource_group_name" {
    type        = string
    description = "RG name in Azure"
}
variable "resource_group_location" {
    type        = string
    description = "RG location in Azure"
}

Then your main.tf file should be:

module "app_service_test" {
  source                  = "./modules/appservice"
  app_service_plan_name   = "ger-plan-test"
  app_service_name        = "ger-site-test"
  resource_group_location = "West Europe"
  resource_group_name     = "geralexgr-terraform-rg"
}

module "storage_account_test" {
  source                  = "./modules/storageaccount"
  storage_account_name    = "geralexgrsgv2"
  resource_group_name     = "geralexgr-terraform-rg"
  resource_group_location = "West Europe"
}

10 thoughts on “Pass variables values inside terraform modules

  1. In the first method, do we need to define the same variable in the root module (appservice) and also in our code where we are referring to that module?

    1. Indeed Sunil. With the first method you bypass the need of passing variables when calling the module. Inside each module only the definitions of the variables exist and you pass all variables in the root module terraform.tfvars

      1. Thank you very much for your swift response dear friend,

        I am in a situation where i am trying to Azure terraform-azurerm-aks module (built and owned by azure), for example, if you take the folder inside this repository, there is something called as ‘examples/with_acr’, where it has the reference to the terraform module, https://github.com/Azure/terraform-azurerm-aks/blob/main/examples/with_acr/main.tf#L58 – I want to pass this value as per my environment (dev, test and prod), i see that this has already been mentioned in the variables.tf inside the module, https://github.com/Azure/terraform-azurerm-aks/blob/main/variables.tf#L492, what i am assuming is as it is already defined inside the module, can’t we pass this through the terraform.tfvars, how do i make this value to be dynamic in my code? Please help me on this.

        1. I have an example for that. I hope this article helps you. https://blog.geralexgr.com/automation/create-multiple-environments-with-terraform-modules-app-service-azure-example . I believe is somehow what you need.

          1. Please stay with me on this, i am going to provide you a example with a branch of your code, I am trying to push those changes, this will give you an idea what i am trying to do.

          2. @geralexgr, could you please look into this pull request that i had created for your repository?
            https://github.com/geralexgr/terraform-module-environments-deploy/pull/1

  2. Thank you very much for your swift response dear friend, I am in a situation where i am trying to Azure terraform-azurerm-aks module (built and owned by azure), for example, if you take the folder inside this repository, there is something called as ‘examples/with_acr’, where it has the reference to the terraform module, github.com/Azure/terraform-azurerm-aks/blob/main/examples/with_acr/main.tf#L58 – I want to pass this value as per my environment (dev, test and prod), i see that this has already been mentioned in the variables.tf inside the module, https://github.com/Azure/terraform-azurerm-aks/blob/main/variables.tf#L492, what i am assuming is as it is already defined inside the module, can’t we pass this through the terraform.tfvars, how do i make this value to be dynamic in my code? Please help me on this.

  3. It seems inefficient and not “DRY” (Don’t Repeat Yourself) to have to duplicate the same variables in multiple places. Is this really the best Terraform can do? I saw someone use outputs.tf to define variables and then import those outputted variables as a “globals” type of approach. I’m not loving either method above, but understand it can be done those ways.

    1. indeed, we could not describe the mentioned methods as a DRY methodology but we could say that terraform is not oop and those concepts cannot be replicated 100% percent in iac languages.

  4. […] Pass variables values inside terraform modules […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.