Skip to content

Terragrunt Structure Reference

Before You Read

This page is a reference. For context on why Terragrunt is used see Terraform & Terragrunt. For making changes see Change Management.

Directory Layout

infrastructure-management/
├── modules/                           ← Reusable Terraform modules (see Terraform Modules Reference)
│   ├── k8s/
│   ├── network/
│   ├── datastore/
│   ├── redis/
│   ├── artifacts/
│   ├── secretmanager/
│   ├── secretmanager-version/
│   ├── service-accounts/
│   ├── helm/
│   │   └── AppsIngress/               ← Gateway + VirtualService templates
│   ├── dns/
│   ├── buckets/
│   ├── users-access/
│   ├── cert-monitor/
│   │   └── scripts/
│   │       ├── monitor.py
│   │       └── Dockerfile
│   ├── kms/
│   ├── cloudsql-root-password/
│   └── cloudsql-microservice-credentials/
└── projects/
    ├── orofi-dev/                     ← Development environment
    │   ├── local.tf                   ← Backend config + local variables
    │   ├── network.tf                 ← VPC, subnets, firewall, static IP
    │   ├── k8s.tf                     ← GKE cluster
    │   ├── sql.tf                     ← Cloud SQL instance + root password
    │   ├── redis.tf                   ← Cloud Memorystore Redis
    │   ├── artifacts.tf               ← Artifact Registry (docker + maven)
    │   ├── service-accounts.tf        ← All microservice + platform service accounts
    │   ├── secrets.tf                 ← All Secret Manager secrets
    │   ├── dns.tf                     ← Cloud DNS records
    │   ├── buckets.tf                 ← GCS buckets
    │   ├── kms.tf                     ← KMS key ring for identity service
    │   ├── helm.tf                    ← Istio + cert-manager + ArgoCD
    │   └── users-access.tf            ← Engineer IAM bindings
    ├── orofi-staging/                 ← Staging environment (same file structure)
    │   ├── local.tf
    │   ├── network.tf
    │   ├── k8s.tf
    │   ├── sql.tf
    │   ├── redis.tf
    │   ├── service-accounts.tf
    │   ├── secrets.tf
    │   ├── dns.tf
    │   └── ...
    └── orofi-prod/                    ← Production (sparse — some resources managed manually)
        └── local.tf

Variable Inheritance

Unlike pure Terragrunt (which uses terragrunt.hcl inheritance), this repo uses standard Terraform with local.tf files that define environment-specific locals. There is no Terragrunt parent/child hierarchy — each project is self-contained.

local.tf Pattern

# infrastructure-management/projects/orofi-staging/local.tf

terraform {
  backend "gcs" {
    bucket = "oro-infra-stag"
    prefix = "terraform/automation/staging"
  }
}

provider "google" {
  project = "orofi-stage-cloud"
  region  = "us-central1"
}

locals {
  project_id   = "orofi-stage-cloud"
  env          = "stage"
  region       = "us-central1"
  zone         = "us-central1-a"
  domain       = "*.stage.orofi.xyz"
  network_cidr = "11.0.0.0/16"
}

All module calls in the same directory reference these locals:

# infrastructure-management/projects/orofi-staging/k8s.tf
module "k8s" {
  source     = "../../modules/k8s"
  project_id = local.project_id   # → "orofi-stage-cloud"
  env        = local.env           # → "stage"
  region     = local.region        # → "us-central1"
  zone       = local.zone          # → "us-central1-a"
}

Adding a New Resource

To add a new GCP resource to an environment:

  1. If a module exists: add a module call to the appropriate .tf file in projects/orofi-{env}/
  2. If no module exists: create a new module in modules/ following the existing patterns
  3. Run terraform plan to validate, then terraform apply

Example: Adding a new secret to staging

# infrastructure-management/projects/orofi-staging/secrets.tf
module "new_feature_secret" {
  source     = "../../modules/secretmanager"
  project_id = local.project_id
  secret_id  = "${local.env}-new-feature-secret"
}

Then add the secret ID to the appropriate service account's secret_ids list in service-accounts.tf.

Adding a New Environment

To create a new environment (e.g., a qa environment):

  1. Create infrastructure-management/projects/orofi-qa/
  2. Copy local.tf from an existing environment and update all values
  3. Copy each .tf resource file, adjusting module inputs as needed
  4. Create a new GCS bucket for Terraform state
  5. Create a Terraform service account in the new GCP project
  6. Run terraform init then terraform apply

State Management

Each project maintains its own state:

Environment Bucket Prefix
Dev oro-dev-infra terraform/oro/dev
Staging oro-infra-stag terraform/automation/staging
Production oro-infra-production terraform/automation/production

State buckets themselves are not managed by Terraform (bootstrapping problem) — they were created manually and must not be deleted.

Running Terraform

# Initialize (do this once, or after changing backend/providers)
cd infrastructure-management/projects/orofi-dev
terraform init

# Authenticate as the Terraform service account
gcloud auth activate-service-account terraform-mnl@orofi-dev-cloud.iam.gserviceaccount.com \
  --key-file=/path/to/key.json

# Or use application default credentials if you have sufficient permissions
gcloud auth application-default login

# Plan
terraform plan

# Apply
terraform apply

# Apply a specific resource (useful during development)
terraform apply -target=module.microservice_identity_sa

See Change Management for the full safe-change process.

See Also