Terraform 34: Terraform Modules 2: Writing your own module
easy⏱ 5 mincourseterraform
Inputs in, outputs out
Anatomy of a module folder: variables.tf declares typed inputs (some with defaults), main.tf builds resources from them, and outputs.tf exposes values the caller needs. Inputs are the only way in; outputs are the only way out.
# modules/resource-group/variables.tf
variable "environment_name" {
type = string
}
variable "service" {
type = string
}
variable "location" {
type = string
default = "westus2"
}
# modules/resource-group/main.tf
resource "azurerm_resource_group" "rg" {
name = "myorg-${var.service}-${var.environment_name}-rg"
location = var.location
}
# modules/resource-group/outputs.tf
output "name" {
value = azurerm_resource_group.rg.name
}
output "id" {
value = azurerm_resource_group.rg.id
}
Type your variables, default the optional ones
Always give a type. Add default only for values a caller can reasonably skip (like location). Inputs with no default are required — a caller that omits them fails validation, which is exactly the guardrail you want for critical settings.
Don't hardcode the environment inside the module
Keep modules environment-agnostic: never bake dev into a name or a SKU. Pass environment_name as an input so the same module serves dev, uat, and prod. Hardcoding kills reuse — the whole point of a module.
Implement the naming convention
The module names resource groups as myorg-<service>-<env>-rg. Write resourceGroupName(service, env) returning that string and log resourceGroupName("orders", "dev") — expect myorg-orders-dev-rg.