
Le bloc resource est la brique de base de Terraform : il déclare un objet
à créer et à maintenir. Le déclarer est simple. Ce qui compte vraiment, et ce que
l'examen interroge, c'est de savoir lire, avant d'appliquer, ce que Terraform
va faire à cette ressource : la créer, la mettre à jour en place, la remplacer,
ou la détruire.
Ce guide part de la base, la syntaxe et l'adressage, puis montre comment les
références ordonnent les ressources, et enfin comment lire les quatre
opérations du cycle de vie dans le plan au format JSON. Les exemples ont été
vérifiés sur Terraform v1.15.4 avec local, random et terraform_data,
sans cloud.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- La syntaxe d'un bloc
resource: type, nom, arguments - Pourquoi le couple type + nom est l'adresse dans le state
- Comment une référence ordonne les ressources, sans
depends_on - Les quatre opérations du cycle de vie, et leur signature dans le plan
terraform_data, la ressource intégrée sans provider- Lire le plan et le state de façon structurée (
-json)
Prérequis
Section intitulée « Prérequis »- Providers et premiers pas (providers, resources et data sources)
- Terraform 1.15.x, la série stable courante
Qu'est-ce qu'un bloc resource ?
Section intitulée « Qu'est-ce qu'un bloc resource ? »Un bloc resource déclare un objet que Terraform crée, met à jour et
détruit. Sa syntaxe tient en trois parties :
resource "local_file" "rapport" { filename = "rapport.txt" content = "bonjour"}local_fileest le type, fourni par un provider (icilocal). Une exception :terraform_dataest un type intégré, il n'appartient à aucun provider.rapportest le nom local.- Le corps contient les arguments de l'objet.
On référence la ressource par local_file.rapport, et ses attributs par
local_file.rapport.<attribut>.
L'adresse est la clé du state
Section intitulée « L'adresse est la clé du state »Le couple type + nom n'est pas qu'un alias de code : c'est l'adresse de la ressource dans le fichier d'état. La documentation le dit : « Terraform uses the resource type and name as the resource's address in your workspace's state file. »
La conséquence est concrète et surprend souvent : renommer une ressource
détruit l'objet et le recrée, parce que Terraform voit l'ancienne adresse
disparaître et une nouvelle apparaître. Pour renommer sans détruire, il faut un
bloc moved, traité dans le lab de migration for_each.
Les références ordonnent les ressources
Section intitulée « Les références ordonnent les ressources »Quand une ressource référence un attribut d'une autre, Terraform en déduit l'ordre. C'est la dépendance implicite, et elle suffit dans l'immense majorité des cas :
resource "random_pet" "hote" { length = 2}
resource "local_file" "fiche" { filename = "fiche-${random_pet.hote.id}.txt" content = "hote=${random_pet.hote.id}\n"}local_file.fiche référence random_pet.hote.id : Terraform crée l'hôte, puis
la fiche. Aucun depends_on n'est nécessaire, et en ajouter un ici serait
redondant. Le meta-argument depends_on ne sert qu'aux dépendances de
comportement qu'aucune référence ne peut exprimer : voir
depends_on en Terraform.
Les quatre opérations du cycle de vie
Section intitulée « Les quatre opérations du cycle de vie »Voici le cœur du sujet, et ce que l'examen interroge. Terraform ne fait que quatre choses à une ressource, et chacune a une signature dans le plan JSON.
| Opération | actions dans le plan |
|---|---|
| Créer | ["create"] |
| Mettre à jour en place | ["update"] |
| Remplacer (détruire puis créer) | ["delete", "create"] |
| Détruire | ["delete"] |
Une cinquième valeur, ["no-op"], signale qu'il n'y a rien à faire. Tout le
sujet consiste à distinguer une mise à jour en place d'un remplacement :
l'une modifie l'objet, l'autre le recrée.
Le montage de démonstration
Section intitulée « Le montage de démonstration »Ce petit montage suffit à provoquer les deux opérations qui comptent, une mise à jour en place et un remplacement, sans aucun provider distant :
variable "niveau" { type = string default = "beta"}
variable "cycle" { type = number default = 1}
resource "random_pet" "serie" { length = 2 keepers = { cycle = var.cycle }}
resource "terraform_data" "jeton" { input = var.niveau triggers_replace = random_pet.serie.id}terraform_data est une ressource intégrée qui offre le cycle de vie
complet sans aucun provider : son argument input se met à jour en place, et
triggers_replace force un remplacement quand la valeur suivie change.
Lire une mise à jour en place
Section intitulée « Lire une mise à jour en place »Changez le niveau. L'argument input change, mais rien n'impose de recréer :
terraform apply -auto-approveterraform plan -var 'niveau=stable' -out=tfplanterraform show -json tfplan | jq -c '.resource_changes[] | select(.address=="terraform_data.jeton") | .change.actions'["update"]["update"] : l'objet est modifié, pas recréé. C'est le cas le moins coûteux.
Lire un remplacement
Section intitulée « Lire un remplacement »Changez le cycle. Les keepers en dépendent, donc random_pet.serie est
remplacé, son id change, et le triggers_replace du jeton déclenche à son
tour un remplacement :
terraform plan -var 'cycle=2' -out=tfplanterraform show -json tfplan | jq -c '.resource_changes[] | select(.address=="terraform_data.jeton") | .change.actions'["delete", "create"]["delete", "create"] : détruit puis recréé. Ce n'est pas anodin, l'objet est
neuf. Pour inverser cet ordre et supprimer la fenêtre où l'objet n'existe plus,
c'est create_before_destroy, traité dans
le bloc lifecycle Terraform.
Inspecter le plan et le state de façon fiable
Section intitulée « Inspecter le plan et le state de façon fiable »terraform state list et terraform state show produisent une sortie
humaine, pratique à lire mais non contractuelle. Pour un script ou un
contrôle, seules les formes structurées sont stables :
terraform show -json | jq '.values.root_module.resources[] | {address, mode}'terraform plan -detailed-exitcode # 0 = aucun changement, 2 = des changementsterraform output -jsonterraform plan -detailed-exitcode rend 0 quand la configuration est
stable, 2 quand des changements restent à appliquer : c'est le test
d'idempotence de tout workflow en automation.
Provisioners : en dernier recours
Section intitulée « Provisioners : en dernier recours »Un bloc provisioner exécute une commande locale ou distante lors de la
création ou de la destruction. La documentation officielle le déconseille :
« We recommend using configuration management tools or other means to perform
actions on the local or remote machine instead of using the provisioner
block. » Réservez-le aux cas qu'aucune ressource de provider ne couvre.
Dépannage
Section intitulée « Dépannage »Ces symptômes se lisent tous dans le plan, avant l'apply. Le tableau associe chaque signature d'action à ce qu'elle signifie réellement.
| Symptôme | Cause | Solution |
|---|---|---|
| Une ressource est remplacée alors qu'on attendait une mise à jour | Un attribut modifié ne peut pas être changé en place | Normal si l'API distante l'impose ; le plan montre ["delete", "create"] |
| Une ressource est détruite puis recréée après un simple renommage | Le nom fait partie de l'adresse dans le state | Utiliser un bloc moved pour renommer sans détruire |
Invalid single-argument block definition | Un bloc mono-ligne à deux arguments | Écrire le bloc en multi-lignes, un argument par ligne |
Resource already exists | L'objet existe hors de Terraform | L'importer avec un bloc import {} |
Un depends_on ajouté ne change rien | Il double une référence déjà présente | Le supprimer : la référence ordonne déjà |
À retenir
Section intitulée « À retenir »- Un bloc
resourcea un type (du provider, saufterraform_data) et un nom local. - Le couple type + nom est l'adresse dans le state : renommer détruit
et recrée, sauf bloc
moved. - Une référence ordonne les ressources ;
depends_onn'est qu'un dernier recours. - Terraform ne fait que quatre opérations, chacune avec sa signature :
["create"],["update"],["delete", "create"],["delete"]. - Distinguer mise à jour en place et remplacement est le point clé, et le plan JSON le donne avant l'apply.
terraform_dataoffre le cycle de vie complet sans provider.- Les formes
-jsonetplan -detailed-exitcodesont les seules stables pour un contrôle.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous reprennent les points qui reviennent le plus souvent :
l'adresse comme clé du state, le choix entre référence et depends_on, et la
lecture des opérations dans le plan.
Trois parties
resource "local_file" "rapport" {
filename = "rapport.txt"
content = "bonjour"
}
local_file: le type, fourni par un provider.rapport: le nom local.- Le corps : les arguments de l'objet.
L'exception terraform_data
terraform_data est un type intégré : il n'appartient à aucun provider et offre un cycle de vie complet sans en installer un.L'adresse est la clé du state
La documentation l'énonce : « Terraform uses the resource type and name as the resource's address in your workspace's state file. »Le couple type + nom n'est donc pas qu'un alias de code.La conséquence
Renommer une ressource fait disparaître une adresse et apparaître une autre. Terraform détruit l'objet à l'ancienne adresse et le recrée à la nouvelle.La parade
Un blocmoved déclare le réadressage, et Terraform déplace l'entrée dans le state au lieu de recréer l'objet.La référence suffit
resource "local_file" "fiche" {
filename = "fiche-${random_pet.hote.id}.txt"
content = "hote=${random_pet.hote.id}\n"
}
local_file.fiche référence random_pet.hote.id : Terraform crée l'hôte, puis la fiche. C'est la dépendance implicite.depends_on est un dernier recours
Il ne sert qu'aux dépendances de comportement qu'aucune référence ne peut exprimer. Posé en double d'une référence, il est redondant et rend le plan plus conservateur.Quatre opérations, quatre signatures
| Opération | actions dans le plan |
|---|---|
| Créer | ["create"] |
| Mettre à jour en place | ["update"] |
| Remplacer | ["delete", "create"] |
| Détruire | ["delete"] |
["no-op"], signale l'absence de changement.Le point clé
Distinguer une mise à jour en place (["update"], indolore) d'un remplacement (["delete", "create"], l'objet est recréé).Lire le plan JSON
terraform plan -out=tfplan
terraform show -json tfplan | jq -c '.resource_changes[] | {address, actions: .change.actions}'
Interpréter
["update"]: mise à jour en place, l'objet est modifié.["delete", "create"]: remplacement, l'objet est recréé.
Un cycle de vie sans provider
terraform_data est une ressource intégrée :resource "terraform_data" "jeton" {
input = var.niveau
triggers_replace = random_pet.serie.id
}
input: se met à jour en place quand il change.triggers_replace: force un remplacement quand la valeur suivie change.output: l'attribut calculé qui rend la valeur.
Un usage courant
Elle sert de relais pourreplace_triggered_by, qui n'accepte que des ressources gérées, jamais une variable.Les formes stables
terraform show -json | jq '.values.root_module.resources[] | {address, mode}'
terraform output -json
terraform plan -detailed-exitcode
Pourquoi pas state list ou state show
Leur sortie est humaine, pratique à l'écran mais non contractuelle : elle peut changer entre versions.L'idempotence
terraform plan -detailed-exitcode rend 0 si la configuration est stable, 2 si des changements restent à appliquer. C'est le test de tout workflow en automation.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Les expressions Terraform : Explique comment une ressource se référence et comment les types se convertissent.
- depends_on : les dépendances explicites : Ajoute une dépendance quand aucune référence ne l'exprime.
- Le bloc lifecycle : Détaille les sept règles qui pilotent création, remplacement et destruction.