Fortement typer une variable.
→Primitives : `string`, `number`, `bool`. Collections : `list(<type>)`, `set(<type>)`, `map(<type>)`. Structurelles : `object({...})`, `tuple([...])`. Utiliser `any` uniquement si véritablement polymorphe.
Référence↗
Restreindre `environment` à dev/staging/prod.
→`variable "environment" { validation { condition = contains(["dev","staging","prod"], var.environment); error_message = "..." } }`. Plusieurs blocs `validation` sont autorisés ; tous doivent passer.
Référence↗
Sortir un mot de passe de base de données sans qu'il n'apparaisse dans `terraform output`.
→`output "db_password" { value = ...; sensitive = true }`. La CLI affiche `(valeur sensible)`. Toujours lisible via `terraform output db_password` ou `-json` (intentionnellement — pour les scripts).
Référence↗
Calculer une valeur une fois et la réutiliser sur de nombreuses ressources.
→`locals { common_tags = merge(var.tags, { Project = var.project }) }`. Référencer comme `local.common_tags`. Non surchargeable depuis l'extérieur du module.
Référence↗
Rechercher une AMI existante sans la gérer.
→`data "aws_ami" "ubuntu" { most_recent = true; filter { ... } }`. Lecture seule. Référencer les attributs comme `data.aws_ami.ubuntu.id`.
Référence↗
Créer N ressources similaires — choisir `count` ou `for_each`.
→`for_each` (avec map ou set) lorsque les éléments ont une identité stable (noms de régions, clés d'environnement). `count` pour "J'ai besoin de N copies, l'ordre n'a pas d'importance, l'identité est juste un index". L'ajout/suppression au milieu de `count` provoque une destruction/recréation ; `for_each` préserve l'identité.
Référence↗
Créer une ressource par élément dans une liste de chaînes.
→`for_each = toset(["a", "b", "c"])`. `each.key` et `each.value` donnent tous deux la chaîne. Pour les maps : `for_each = var.users` — `each.key` = clé de map, `each.value` = valeur de map.
Référence↗
Générer un nombre variable de blocs imbriqués (par exemple, règles d'ingress).
→`dynamic "ingress" { for_each = var.rules; content { from_port = ingress.value.from; ... } }`. L'argument `iterator` peut renommer l'itérateur si nécessaire.
Référence↗
Obtenir une liste d'attributs pour toutes les instances d'une ressource `count`.
→`aws_instance.web[*].id` renvoie une liste d'ID. Fonctionne avec `count` et `for_each` (mais `for_each` produit une map non ordonnée, donc `values(aws_instance.web)[*].id`).
Référence↗
Définir une valeur en fonction d'une condition.
→Ternaire : `var.is_prod ? 5 : 1`. Les deux branches doivent produire le même type.
Référence↗
Combiner deux maps ; les valeurs du second l'emportent en cas de collision de clés.
→`merge(local.defaults, local.overrides)`. La map la plus à droite l'emporte. Utile pour la composition de tags.
Référence↗
Lire une valeur de map avec une valeur par défaut si la clé est manquante.
→`lookup(var.config, "region", "us-east-1")`. Retourne la valeur par défaut si la clé n'est pas présente. Pour les structures profondément optionnelles, préférer la fonction optionnelle `try()`.
Référence↗
Aplatir les listes imbriquées en une liste simple.
→`flatten([["a","b"], ["c"], [["d","e"]]])` → `["a","b","c","d","e"]`. Aplatit récursivement les listes ; préserve l'ordre.
Référence↗
Intégrer une map Terraform dans un document de politique IAM.
→`jsonencode({Version = "2012-10-17", Statement = [...]})`. Produit une chaîne JSON. Inverse : `jsondecode()`.
Référence↗
Rendre un script user-data templatisé avec des valeurs provenant de variables.
→`templatefile("init.sh.tpl", { region = var.region, env = var.env })`. Le template utilise la syntaxe `${region}`. Alternative plus récente pour le rendu statique : `file()` + `format()`.
Référence↗
Découper les CIDR de sous-réseaux à partir d'une plage de VPC.
→`cidrsubnet("10.0.0.0/16", 8, 0)` → `10.0.0.0/24`. Premier argument = parent, deuxième = bits à étendre, troisième = numéro de sous-réseau.
Référence↗
Lire une valeur qui pourrait ne pas exister ; revenir à une valeur par défaut.
→`try(yamldecode(file("config.yaml")), { defaults = true })`. Évalue de gauche à droite ; retourne la première expression sans erreur.
Référence↗
Itérer sur les fichiers correspondant à un glob.
→`fileset(path.module, "configs/*.json")` retourne un ensemble de chemins. À combiner avec `for_each` pour gérer une ressource par fichier.
Référence↗
Même provider dans deux régions (par exemple, AWS us-east-1 + us-west-2).
→Deux blocs `provider "aws" { alias = "..." }`. Les ressources optent via `provider = aws.us_west`. Les modules acceptent les alias via `configuration_aliases`.
Référence↗
Exécuter une commande shell sur une VM nouvellement créée.
→Provisioner `remote-exec` à l'intérieur d'une ressource. Outil de dernier recours — préférer cloud-init, user data, ou la gestion de configuration. Les provisioners ne sont pas suivis dans l'état et ne se réexécutent pas en cas de dérive.
Référence↗
Exécuter une commande qui ne correspond pas à une ressource cloud (par exemple, invocation CLI).
→`resource "null_resource" "trigger" { triggers = { sha = sha1(file(".")) }; provisioner "local-exec" { command = "..." } }`. Se réexécute lorsque les `triggers` changent.
Référence↗
Vérifier en continu un invariant d'exécution (par exemple, un endpoint de santé retourne 200) sans bloquer l'apply.
→`check "endpoint" { data "http" "h" { url = "..." }; assert { condition = data.http.h.status_code == 200; error_message = "..." } }`. S'exécute lors du plan/apply ; l'échec est un avertissement, pas une erreur bloquante.
Pourquoi: `check` autorise des sources de données locales utilisables uniquement à l'intérieur du check. `precondition`/`postcondition` sont des erreurs bloquantes au plan/apply.
Référence↗
Faire échouer le plan si une AMI est trop ancienne.
→`lifecycle { precondition { condition = data.aws_ami.x.creation_date > "2024-01-01"; error_message = "..." } }`. Échec bloquant, évalué avant/après selon le cas.
Référence↗
Variable avec une valeur positionnelle de forme fixe.
→`type = tuple([string, number, bool])` exige exactement trois éléments dans cet ordre. Différent d'une liste (homogène, longueur variable).
Référence↗
Fortement typer une entrée structurée (par exemple `database = { instance_class = string, allocated_storage = number }`).
→`type = object({ instance_class = string, allocated_storage = number, multi_az = optional(bool, false) })`. `optional(<type>, <default>)` rend les attributs optionnels.
Référence↗
Comment les fichiers `*.tfvars` sont-ils chargés ?
→`terraform.tfvars` et `*.auto.tfvars` se chargent automatiquement (ordre lexical pour `auto`). D'autres noms nécessitent `-var-file=path.tfvars`.
Référence↗
Écrire des tests automatisés pour un module Terraform.
→Fichiers `.tftest.hcl` avec `run "name" { command = plan|apply, assert { condition = ..., error_message = ... } }`. `command = plan` est sans effets secondaires ; `command = apply` crée réellement des ressources.
Référence↗
Passer des variables dans les exécutions de test.
→Le bloc `variables { ... }` au niveau du fichier s'applique à toutes les exécutions. Le bloc `variables { ... }` par exécution surcharge pour cette exécution uniquement.
Référence↗