AWS Terragrunt DRY IaC Design and implementation
Sixteen Terraform modules behind one root config, with Terragrunt running them in order from their dependency graph.
The provider generated from the root
What this code does: Terragrunt’s generate block writes a provider.tf file into each unit folder. The region comes from the region settings, the Environment tag from the account name, and every resource automatically gets a ManagedBy = terragrunt tag. The last line merges the account and region locals into the common inputs of every unit, so a unit file keeps only the values specific to that unit.
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<PROVIDER
provider "aws" {
region = "${local.aws_region}"
default_tags {
tags = {
Environment = "${local.account_name}"
ManagedBy = "terragrunt"
}
}
}
PROVIDER
}
inputs = merge(local.account_vars.locals, local.region_vars.locals)
dependency and mock_outputs
What this code does: Declares that this unit depends on the elastic_ip unit in the neighboring folder. From this, Terragrunt runs elastic_ip first and passes its output (eip_id) into this unit as input. When no real output exists yet, the fake IDs in mock_outputs are used, but only for init, validate, and plan, so the whole stack can be validated without a cloud while fake values can never reach a real apply.
dependency "elastic_ip" {
config_path = "${get_terragrunt_dir()}/../elastic_ip"
mock_outputs = {
eip_id = {
"demo-eip-1" = "eipalloc-00000000000000001"
"demo-eip-2" = "eipalloc-00000000000000002"
}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
}