The DevOps Jedi

Taking the cloud by storm one line of code at a time....

Use Of Terraform Child Modules

2023-01-203 min readDarren Johnson

Terraform uses the construct of a module, which is defined by HashiCorp as “a set of Terraform configuration files in a single directory”.

The root module consists of resources defined in the main working directory (which I like to refer to as the ’execution folder’). However, you can also call other modules to include their configuration. These are known as child modules which can be shared and reused by multiple root module configurations. Sounds good, doesn’t it?

Well, there is a drawback to this approach. Let me explain.

Let’s say your configuration contains a key vault that is deployed via module. Each argument in the module either needs to be supplied via a variable from the root module or becomes a hard coded setting for the resource. An example of how this child module could look is below:

resource "azurerm_key_vault" "blog_msdn" {
  name                = var.name
  location            = var.location
  resource_group_name = var.resource_group_name
  sku_name            = var.sku_name
  tenant_id           = var.tenant_id
}

To call the child module, the root module would need to specify the relative location of the child module and the arguments to pass it:

module "key_vault_blog_msdn" {
  source              = "../modules/key-vault"
  name                = "mykeyvault"
  location            = "westeurope"
  resource_group_name = "myresourcegroup"
  sku_name            = "standard"
  tenant_id           = "mytenantid"
}

Let’s say this module gets used in anger and a new capability is introduced that allows you to enable soft delete. In order to use this new capability, you need to use a new major version of the azurerm module. For the sake of brevity, a new argument named soft_delete_enabled with a value of var.soft_delete_enabled has been added.

If the child module is updated every root module that consumes the child module will be affected and will need to be updated to add soft_delete_enabled = true or the configuration will not apply. The following problems could also occur as a result of the change:

  • Existing terraform configurations consuming the child module do not support the updated major version. This could be mitigated by creating another version (copy) of the module and reverting the changes. However, this then leads to ‘module sprawl’ with multiple copies of the same modules that differ slightly and makes the modules difficult to manage.

  • The default behaviour of the module and/or terraform resource has changed after the update and unwanted changes are applied. For example, if they key vault was created using an older version of the API before the Soft Delete feature was enforced, there would have been no default value. The updated module then enables Soft Delete, and you would have no way of turning it off.

Key Takeaway: When making changes to child modules you always introduce some risk to resources that have already been deployed. Every root module will need to be either updated to cater for the changes or accept a default value that will apply to every resource built via the child module. For this reason alone, I do not use child modules as part of my terraform configurations. This has the added benefit of no code dependencies outside of the root module, and all changes are isolated to that folder only.

Saying all the above I still like to standardise on code for common resources, but I do that by using template Terraform code with a PowerShell wrapper to generate the unique code required. That is a subject for another post in itself.