Terraform Code Smells - The Middleman
20 Jul 2022Infrastructure as Code has code smells (its code too !!) and as we work more with it, it’s important to be aware of code smells that indicate a deeper problem.
The Middleman doesn’t do anything other than delegate to a native resource
Let’s look at an example;
module storage_account {
source = "./module/resource-group"
name = var.storage_account_name
resource_group_name = var.resource_group_name
location = var.location
account_tier = var.account_tier
account_replication_type = var.account_replication_type
tags = {
environment = "staging"
}
}
Here we see a module that creates a storage account. Let’s look inside the module itself.
resource "azurerm_storage_account" "storage_account" {
name = var.storage_account_name
resource_group_name = var.resource_group_name
location = var.location
account_tier = var.account_tier
account_replication_type = var.account_replication_type
tags = var.tags
}
The module has a single resource. The variables are delegated to the resource. There are no collaborating resources inside the module.
Why is this a code smell?
The module itself does not add any value over using the native resource directly, and is a thin wrapper around the single resource. A Terraform module is a group of resources that work together cohesively.
This code smell appears because of the need to control what types of resources are used in the organisation’s context. We can use Azure Policy and AWS Guardrails to achieve the same result
Another reason is the need to deploy resources consistently across the organisation. For example, to apply tags consistently. Again we can use policies to enforce consistent rules.
Does it satisfy the five CUPID properties?
- Unix philosophy: Does it do one thing well? it does, but all it does is delegate. The work is done by the resource that is wrapped in the module
- Predictable: Does it do what you expect? It’s unclear why a module is used than using the resource directly
- Idiomatic: Does it feel natural? It introduces an extra level of in-direction compared to using the resource directly
- Domain-based: does the solution model the problem domain? The module doesn’t model the domain, it duplicates what Terraform does
Treatment
Avoid wrapping single resources with modules. Terraform modules are composed of resources that work together to provide a cohesive building block. Get rid of the middleman.