The live tree¶
Everything deployable lives under live/. This page explains how the tree is
organised, what counts as a unit, and how the engine and Terragrunt find things in
it.
Folder names are management group IDs¶
Inside live/, the folder tree mirrors the Cloud Adoption Framework management group
hierarchy, and each folder is named after the management group ID it represents.
live/ # the alz root management group
├── platform/ # MG: platform
│ ├── connectivity/ # MG: connectivity
│ ├── identity/ # MG: identity
│ ├── management/ # MG: management
│ └── security/ # MG: security
├── landingzones/ # MG: landingzones
│ ├── corp/ # MG: corp
│ ├── online/ # MG: online
│ └── local/ # MG: local (Azure Local, rarely used)
├── sandbox/ # MG: sandbox
└── decommissioned/ # MG: decommissioned
Every one of those names matches an entry in the architecture definition in
the vendored policy library. The alz root itself has no folder
of its own. live/ is that level.
_foundation/ is the deliberate exception. It is not a management group. The
underscore sorts it to the top of the tree and marks it as special, because the
foundation is tenant-global rather than belonging to any single management group.
The four levels¶
Below a management group folder, the tree narrows scope in a fixed order.
| Level | Named after | Holds |
|---|---|---|
| Management group | The MG ID. | Child MG folders, or a subscription. |
| Subscription | The subscription's purpose, for example corp-workload. |
subscription.hcl, then region folders. |
| Region | The Azure region, for example westeurope. |
region.hcl, then units. Use _global for region-agnostic work. |
| Unit | What it deploys, for example network. |
terragrunt.hcl and main.tf. |
A platform management group with exactly one subscription flattens the subscription
level away and puts subscription.hcl directly in the management group folder.
_foundation/ flattens further still: it carries both subscription.hcl and
region.hcl at its own root, with units directly under it.
A worked path, from a real deployment:
live/landingzones/corp/corp-workload/westeurope/network/
└─ MG ──┘└ MG ┘└ subscription ┘└ region ─┘└ unit ┘
What a unit is¶
A unit is a leaf folder containing a terragrunt.hcl. That is the whole definition.
It pairs two files:
terragrunt.hclincludes the root contract, generates the backend, the providers, and the context, pins the subscription, and declares ordering dependencies. It carries no resources.main.tfis plain Terraform. It sources an Azure Verified Module at a pinned version and sets its inputs.
The template ships exactly three units, all under live/_foundation/. Everything
else in the tree is a README-only placeholder. A folder with no terragrunt.hcl is
not a unit, so discovery walks straight past it and it costs nothing at plan time.
Resource names inside units follow <abbreviation>-<purpose>-<location_short>, for
example rg-management-weu and uami-amba-weu.
The scope files¶
Three files carry scope rather than resources. They set the context a unit inherits.
| File | Sets | Sits at |
|---|---|---|
tenant.hcl |
Tenant ID and the management group the hierarchy is built under. | live/ root, once. |
subscription.hcl |
The subscription a subtree deploys into. | Each subscription scope. |
region.hcl |
The region and environment for a subtree. | Each region scope. |
Units never include these directly. They include root.hcl, which walks up the tree
to find them. The nearest ancestor wins, so a connectivity unit picks up a different
subscription from the foundation with no per-unit wiring. See
The root contract.
How things are found¶
Three separate mechanisms, and it helps to keep them apart.
Configuration inheritance walks upward. find_in_parent_folders from the unit
locates root.hcl, and root.hcl in turn locates tenant.hcl, subscription.hcl,
and region.hcl. Nothing is registered anywhere. Position in the tree is the wiring.
The values it finds are written into each unit as a generated context.tf, so
main.tf reads them as plain Terraform.
State keys derive from position. root.hcl sets the backend key to
${path_relative_to_include()}/terraform.tfstate, so a unit's path under live/ is
its state key. Each unit gets its own state file.
Engine discovery is driven by projects.yml at the repository root, which sets
root: live as the scan root and include_dependents: true so a change to a unit
also re-plans anything downstream of it. See
Workflows and discovery config.
Moving a folder moves its state
Because the state key is the path, renaming or moving a unit points it at a new, empty state file. Terraform will plan to create everything the unit already manages. Move the state blob first, or expect a plan that destroys and recreates. The runbook has the safe procedure.
Ordering¶
Ordering is declared, never inferred. A unit's terragrunt.hcl names the units that
must apply before it in a dependencies block. That block sets order only and reads
no values.
Across the tree the order is _foundation/ first, because management groups must
exist before anything can be placed in them, then platform/ for the connectivity
hubs, then landingzones/. Within the foundation the order is management-resources,
then landing-zones, then amba.
Next: The root contract.