📗 Terragrunt#

Référentiel des blocs de configuration Terragrunt#

Vue d’ensemble#

Bloc

Type

Rôle

terraform

Block

Configurer l’exécution Terraform/OpenTofu

remote_state

Block

Configurer le backend d’état

include

Block

Hériter d’une configuration parente

locals

Block

Définir des variables réutilisables

dependency

Block

Accéder aux outputs d’un autre module

dependencies

Block

Orchestrer l’ordre d’exécution

generate

Block

Générer des fichiers HCL/JSON avant l’exécution

feature

Block

Flags de fonctionnalité

exclude

Block

Exclure conditionnellement un module

errors

Block

Gérer les erreurs (retry, ignore)

engine

Block

Configurer un moteur d’exécution alternatif

unit / stack

Block

Déclarer des unités/stacks (fichier terragrunt.stack.hcl)

inputs

Attribute

Passer des variables à Terraform


terraform#

Contrôle comment Terragrunt exécute Terraform/OpenTofu.

terraform {
  source = "github.com/org/modules.git//vpc?ref=v1.0.0"

  extra_arguments "common" {
    commands  = get_terraform_commands_that_need_vars()
    arguments = ["-var-file=common.auto.tfvars"]
  }

  before_hook "show_version" {
    commands = ["init", "plan", "apply"]
    execute  = ["terraform", "version"]
  }

  after_hook "show_outputs" {
    commands = ["apply"]
    execute  = ["terraform", "output", "-json"]
  }

  error_hook "handle_failure" {
    commands   = ["apply"]
    on_errors  = [".*Error: timeout.*"]
    execute    = ["echo", "Apply failed due to timeout"]
  }
}

Attribut

Type

Description

source

string (req)

URL ou chemin local du module. Supporte git::, s3::, gcs::, http::, tfr://

copy_terraform_lock_file

bool

Copier .terraform.lock.hcl du cache (défaut: true)

extra_arguments

Block (0+)

Arguments CLI supplémentaires conditionnels

before_hook

Block (0+)

Hook exécuté avant la commande

after_hook

Block (0+)

Hook exécuté après la commande

error_hook

Block (0+)

Hook exécuté en cas d’erreur (matching on_errors)

required_var_files

[]string

Fichiers .tfvars requis (ignorés s’ils n’existent pas)

Hook sub-block attributes :

Attribut

Type

Description

name (label)

string

Identifiant du hook

commands

[]string

Commandes qui déclenchent le hook

execute

[]string

Commande et arguments à exécuter

if

expression

Condition pour exécuter le hook

run_on_error

bool

Exécuter même si une erreur précédente

suppress_stdout

bool

Supprimer la sortie standard

working_dir

string

Répertoire de travail

on_errors

[]string

(error_hook) Regex matchés contre le message d’erreur


remote_state#

Configure le backend d’état et génère automatiquement le fichier backend.tf.

remote_state {
  backend = "s3"

  generate = {
    path      = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }

  config = {
    bucket         = "my-state-bucket"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "my-lock-table"
  }
}

Attribut

Type

Description

backend

string (req)

Nom du backend (s3, gcs, local, etc.)

config

map (req)

Paramètres du backend passés à Terraform

generate

map

Générer un fichier .tf au lieu de passer -backend-config

disable

bool

Désactiver le bloc

generate sub-attributes :

Attribut

Valeurs

path

Chemin du fichier à générer (relatif au working dir)

if_exists

overwrite, overwrite_terragrunt, skip, error


include#

Hérite et fusionne une configuration parente.

include "root" {
  path = find_in_parent_folders("root.hcl")
  expose = true
  merge_strategy = "deep"
}

Attribut

Type

Description

name (label)

string (req)

Identifiant de l’include

path

string (req)

Chemin vers le fichier parent

expose

bool

Rendre accessible via include.<name> (défaut: false)

merge_strategy

string

no_merge, shallow (défaut), deep, deep_map_only

Stratégies de merge :

Stratégie

Comportement

no_merge

Pas de fusion — accès uniquement via include.<name>

shallow

Fusion superficielle (les clés du child remplacent celles du parent)

deep

Fusion profonde (les maps sont fusionnées récursivement)

deep_map_only

Fusion profonde uniquement pour les maps, pas les lists

Accès aux valeurs exposées :

inputs = {
  region = include.root.locals.region
  bucket = include.root.remote_state.config.bucket
}

locals#

Définit des variables réutilisables dans la configuration.

locals {
  env            = "dev"
  region         = "eu-west-1"
  project        = "myapp"
  state_key      = "${local.project}/${local.env}/${path_relative_to_include()}"
  parent_config  = read_terragrunt_config(find_in_parent_folders("env.hcl"))
}

Un seul bloc locals par fichier. Toutes les variables sont préfixées par local..


dependency#

Accède aux outputs d’un autre module Terragrunt.

dependency "vpc" {
  config_path = "../vpc"

  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
  mock_outputs = {
    vpc_id     = "vpc-00000000"
    subnet_ids = ["subnet-aaa", "subnet-bbb"]
  }

  mock_outputs_merge_strategy_with_state = "shallow"
}

inputs = {
  vpc_id     = dependency.vpc.outputs.vpc_id
  subnet_ids = dependency.vpc.outputs.subnet_ids
}

Attribut

Type

Description

name (label)

string (req)

Identifiant (référence via dependency.<name>.outputs)

config_path

string (req)

Chemin relatif vers le terragrunt.hcl du module dépendant

enabled

bool

Activer/désactiver la dépendance (défaut: true)

skip_outputs

bool

Ne pas récupérer les outputs (défaut: false)

mock_outputs

any

Outputs simulés si le module n’est pas encore appliqué

mock_outputs_allowed_terraform_commands

[]string

Commandes où les mock outputs sont autorisés

mock_outputs_merge_strategy_with_state

string

no_merge, shallow, deep, deep_map_only


dependencies#

Orchestre l’ordre d’exécution (sans accéder aux outputs).

dependencies {
  paths = ["../vpc", "../security-group"]
}

Attribut

Type

Description

paths

[]string (req)

Chemins relatifs vers les modules à exécuter d’abord

Différence clé : dependencies ne fait que définir l’ordre ; dependency expose en plus les outputs.


generate#

Génère des fichiers HCL/JSON avant l’exécution de Terraform.

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "aws" {
  region = "${local.region}"
}
EOF
}

generate "tags" {
  path      = "tags.auto.tfvars"
  if_exists = "overwrite"
  contents  = <<EOF
tags = {
  environment = "${local.env}"
  project     = "${local.project}"
}
EOF
}

Attribut

Type

Description

name (label)

string (req)

Identifiant unique

path

string (req)

Chemin du fichier à générer

if_exists

string (req)

overwrite, overwrite_terragrunt, skip, error

contents

string (req)

Contenu du fichier

if_disabled

string

Action si disable = true : skip, remove, error

comment_prefix

string

Préfixe des commentaires de signature (défaut: #)

disable_signature

bool

Omettre l’en-tête “generated by Terragrunt”

disable

bool

Désactiver le bloc


errors#

Gestion des erreurs avec retry et ignore.

errors {
  retry "transient" {
    retryable_errors   = [".*Error: transient network issue.*"]
    max_attempts       = 3
    sleep_interval_sec = 5
  }

  ignore "safe_warnings" {
    ignorable_errors = [".*Warning: deprecated.*"]
    message          = "Ignoring deprecation warnings"
  }
}

Sous-bloc

Attributs

retry "<name>"

retryable_errors (regex), max_attempts, sleep_interval_sec

ignore "<name>"

ignorable_errors (regex, ! pour négation), message


feature#

Flags de fonctionnalité Terragrunt.

feature "terraform_lock" {
  enabled = true
}

exclude#

Exclut conditionnellement un module de l’exécution.

exclude {
  path = "live/us-east-1/dev/legacy-module"
}

engine#

Configure un moteur d’exécution alternatif (ex: OpenTofu au lieu de Terraform).

engine "opentofu" {
  source = "github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_linux_amd64.zip"
}

inputs (attribut, pas un bloc)#

inputs = {
  name       = "my-vpc"
  cidr       = "10.0.0.0/16"
  azs        = ["us-east-1a", "us-east-1b"]
  vpc_id     = dependency.vpc.outputs.vpc_id
  region     = include.root.locals.region
}

Passé directement comme variables à Terraform via -var ou .tfvars.


unit et stack (fichier terragrunt.stack.hcl)#

Nouveauté pour les Stacks Terragrunt — définies dans un fichier terragrunt.stack.hcl distinct de terragrunt.hcl.

# terragrunt.stack.hcl
locals {
  region = "eu-west-1"
}

unit "vpc" {
  source = "github.com/org/modules.git//vpc?ref=v1.0.0"
  path   = "vpc"
  values = {
    cidr_block = "10.0.0.0/16"
  }
}

stack "subnets" {
  source = "github.com/org/modules.git//stacks/subnets?ref=v1.0.0"
  path   = "subnets"
  values = {
    availability_zone = "eu-west-1a"
  }
}

Bloc

Cardinalité

Rôle

locals

0 ou 1

Variables locales du stack

include

0+

Inclure d’autres configurations de stack

unit "<name>"

0+

Déclarer une unité Terragrunt

stack "<name>"

0+

Déclarer un stack imbriqué


Ordre de parsing#

L’ordre dans lequel Terragrunt évalue les blocs est important :

  1. include (de toutes les configurations de l’arbre)

  2. locals (de toutes les configurations de l’arbre)

  3. dependency (de toutes les configurations, sans récupérer les outputs)

  4. terraform (de toutes les configurations)

  5. dependencies (de toutes les configurations)

  6. dependency outputs (récupération réelle)

  7. inputs, generate, remote_state, etc.

Cela signifie qu’on peut référencer local.* dans inputs, et dependency.*.outputs dans inputs, mais pas l’inverse.


Exemple complet combinant plusieurs blocs#

# live/us-east-1/dev/app/terragrunt.hcl

include "root" {
  path = find_in_parent_folders("root.hcl")
}

locals {
  env    = "dev"
  region = "us-east-1"
}

dependency "vpc" {
  config_path = "../vpc"
  mock_outputs = {
    vpc_id     = "vpc-mock"
    subnet_ids = ["subnet-mock"]
  }
}

dependencies {
  paths = ["../vpc", "../security-group"]
}

terraform {
  source = "${get_path_to_repo_root()}//modules/app"
}

inputs = {
  name         = "my-app-${local.env}"
  vpc_id       = dependency.vpc.outputs.vpc_id
  subnet_ids   = dependency.vpc.outputs.subnet_ids
  aws_region   = local.region
}

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "aws" {
  region = "${local.region}"
}
EOF
}

Tour d’horizon des fonctions intégrées de Terragrunt#

Chemins et hiérarchie de configuration#

Fonction

Description

Exemple

find_in_parent_folders([name], [fallback])

Monte l’arborescence et retourne le chemin absolu du premier fichier correspondant. Sans argument, cherche terragrunt.hcl.

include "root" { path = find_in_parent_folders() }

path_relative_to_include([label])

Chemin relatif depuis le fichier parent inclus vers le fichier actuel.

key = "prefix/${path_relative_to_include()}"

path_relative_from_include([label])

Chemin relatif depuis le fichier actuel vers le fichier parent inclus.

get_terragrunt_dir()

Chemin absolu du répertoire contenant le terragrunt.hcl actuel.

path = "${get_terragrunt_dir()}/output"

get_parent_terragrunt_dir([label])

Chemin du répertoire du fichier parent inclus.

get_original_terragrunt_dir()

Chemin du répertoire du terragrunt.hcl enfant d’origine (utile dans read_terragrunt_config).

get_working_dir()

Chemin du répertoire de travail courant.

Exemple typique d’héritage :

# live/us-east-1/dev/mysql/terragrunt.hcl
include "root" {
  path = find_in_parent_folders()
}

locals {
  env_config = read_terragrunt_config(find_in_parent_folders("env.hcl"))
}

remote_state {
  backend = "s3"
  config = {
    bucket = "mycompany-state"
    key    = "us-east-1/${local.env_config.locals.environment}/mysql/terraform.tfstate"
    region = "us-east-1"
  }
}

Lecture de configuration#

Fonction

Description

read_terragrunt_config(path)

Parse un fichier HCL Terragrunt et retourne son contenu (.locals, .inputs, .dependency, etc.) sans fusionner.

read_tfvars_file(path)

Lit un fichier .tfvars ou .tfvars.json et retourne une map.

sops_decrypt_file(path)

Déchiffre un fichier chiffré avec SOPS et retourne le contenu.

Différence clé include vs read_terragrunt_config :

  • include fusionne les blocs (remote_state, generate, terraform, etc.) du fichier parent dans la configuration courante.

  • read_terragrunt_config se contente de lire les données — rien n’est fusionné. On accède aux valeurs via .locals, .inputs, .dependency, etc.

locals {
  root_config   = read_terragrunt_config(find_in_parent_folders("root.hcl"))
  region_config = read_terragrunt_config(find_in_parent_folders("region.hcl"))

  project     = local.root_config.locals.project
  aws_region  = local.region_config.locals.aws_region
}

Variables d’environnement et plateforme#

Fonction

Description

get_env(name)

Retourne la valeur d’une variable d’environnement. Erreur si absente.

get_env(name, default)

Retourne la valeur ou default si la variable n’est pas définie.

get_platform()

Retourne le système d’exploitation courant (linux, darwin, windows).

Git#

Fonction

Description

get_repo_root()

Chemin absolu de la racine du dépôt Git.

get_path_to_repo_root()

Chemin relatif de la racine du dépôt vers le répertoire courant.

get_path_from_repo_root()

Chemin relatif de la racine du dépôt vers le répertoire courant.

terraform {
  source = "${get_path_to_repo_root()}//modules/vpc"
}

AWS#

Fonction

Description

get_aws_account_id()

ID du compte AWS associé aux credentials courants.

get_aws_account_alias()

Alias du compte AWS.

get_aws_caller_identity_arn()

ARN de l’identité appelante (utilisateur ou rôle).

get_aws_caller_identity_user_id()

ID de l’utilisateur appelant.

remote_state {
  backend = "s3"
  config = {
    bucket = "mycompany-${get_aws_account_id()}-state"
  }
}

Commandes et exécution#

Fonction

Description

run_cmd(args...)

Exécute une commande shell et retourne sa sortie standard. Flags disponibles : --terragrunt-quiet, --terragrunt-no-cache, --terragrunt-global-cache.

get_terraform_command()

Retourne la commande Terraform en cours (plan, apply, destroy, …).

get_terraform_cli_args()

Retourne la liste des arguments CLI passés à Terraform.

locals {
  git_commit = run_cmd("git", "rev-parse", "HEAD")
}

Commandes Terraform (pour extra_arguments)#

Fonction

Description

get_terraform_commands_that_need_vars()

Liste des commandes qui nécessitent les variables.

get_terraform_commands_that_need_input()

Commandes qui nécessitent l’input interactif.

get_terraform_commands_that_need_locking()

Commandes qui nécessitent le verrouillage d’état.

get_terraform_commands_that_need_parallelism()

Commandes qui nécessitent le paramètre de parallélisme.

terraform {
  extra_arguments "lock" {
    commands  = get_terraform_commands_that_need_locking()
    arguments = ["-lock-timeout=20m"]
  }
}

Utilitaires et manipulation de données#

Fonction

Description

deep_merge(map1, map2, ...)

Fusionne profondément plusieurs maps/objets.

startswith(str, prefix)

true si la chaîne commence par le préfixe.

endswith(str, suffix)

true si la chaîne se termine par le suffixe.

strcontains(str, substr)

true si la chaîne contient le sous-élément.

timecmp(t1, t2)

Compare deux timestamps (retourne -1, 0, 1).

constraint_check(version, constraint)

Vérifie si une version semver satisfait une contrainte.

get_terragrunt_source_cli_flag()

Retourne la valeur du flag --terragrunt-source passé en CLI.

get_default_retryable_errors()

Retourne la liste des erreurs par défaut considérées comme réessayables.

Suivi de fichiers (pour --filter-affected)#

Fonction

Description

mark_as_read(path)

Marque explicitement un fichier comme lu (affecte le calcul de --filter-affected).

mark_glob_as_read(glob)

Marque tous les fichiers correspondant à un motif glob.

# S'assurer que les fichiers .tf sont considérés comme "lus"
mark_as_read("${get_terragrunt_dir()}/*.tf")
mark_glob_as_read("${get_terragrunt_dir()}/**")

Bonnes pratiques#

  • find_in_parent_folders + read_terragrunt_config est le duo le plus utilisé pour construire une hiérarchie de configuration DRY (racine → région → environnement → module).

  • path_relative_to_include est indispensable pour générer des clés d’état S3/EOS uniques par module sans hardcoder les chemins.

  • run_cmd doit être utilisé avec parcimonie : chaque appel déclenche un processus shell, ce qui ralentit l’évaluation. Privilégier get_env ou des fichiers de configuration statiques quand c’est possible.

  • Toutes les fonctions sont utilisables dans les blocs locals, inputs, remote_state, generate, terraform, include et dependency.