Here's a quick example. Azure is the provider here but that doesn't change the way modules are organized.
This assumes you're using local TF state (probably you'd want to set up a remote state).
Also modules are referenced from the local file system here. You can store them in a separate Git repo (Terragrunt suggested way) for versioning.
An example reusable module at project/resources/resource_group/main.tf
:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 2.26"
}
}
}
resource "azurerm_resource_group" "resource_group" {
name = "${var.project}-${var.environment}-resource-group"
location = var.location
tags = {
project = var.project
environment = var.environment
region = var.location
}
}
# I've included variables and outputs in the same file,
# but it's recommended to put them into separate
# variables.tf and outputs.tf respectively.
variable "project" {
type = string
description = "Project name"
}
variable "environment" {
type = string
description = "Environment (dev / stage / prod)"
}
variable "location" {
type = string
description = "The Azure Region where the Resource Group should exist"
}
output "resource_group_name" {
value = azurerm_resource_group.resource_group.name
}
An example usage of the module in a given environment. Module path is project/test/resource_group/terragrunt.hcl
:
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "azurerm" {
features {}
}
EOF
}
terraform {
source = "../../resources//resource_group"
}
inputs = {
project = "myapp"
environment = "test"
location = "East US"
}
To deploy that specific module (likely it will have more than one resource, unlike in my example), you run terragrunt apply
from project/test/resource_group
.
Alternatively you can execute multiple modules by running terragrunt apply-all
from project/test
.
Honestly, if you're going to use it for projects in production, you better go through Terragrunt documentation, it's quite good.