
Quand Terraform doit remplacer une ressource, il applique un ordre par défaut : il détruit l'ancienne, puis crée la nouvelle. Pour un fichier de configuration, cela n'a aucune importance. Pour une base de données, un équilibreur de charge ou un volume persistant, cela signifie une coupure de service, voire une perte de données.
Le bloc lifecycle existe pour reprendre la main sur ces comportements. Il
se place à l'intérieur d'une ressource et modifie la façon dont Terraform
construit et parcourt son graphe de dépendances. C'est cette phrase qui
explique tout le reste du chapitre, y compris les contraintes qui surprennent.
Ce guide passe en revue les sept règles du bloc, une par une : à quoi
chacune sert, comment elle s'écrit, quand y recourir, et le piège qu'elle
réserve. Tous les comportements décrits ont été vérifiés sur Terraform
v1.15.4, plan JSON à l'appui, avec les seuls providers local, random et la
ressource intégrée terraform_data. Aucun compte cloud n'est nécessaire pour
rejouer les exemples.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Ce qu'est le bloc
lifecycleet où il se place - Les sept règles qu'il accepte, et pourquoi on n'en cite souvent que quatre
create_before_destroy: supprimer la fenêtre de coupure lors d'un remplacementprevent_destroy: refuser un plan destructeur, et ce que cette protection ne couvre pasignore_changes: cesser de proposer des mises à jour sur certains attributsreplace_triggered_by: lier le remplacement d'une ressource à une autrepreconditionetpostcondition: valider avec les valeurs résolues au planaction_trigger: la règle apparue en 1.15.x- Comment prouver un comportement avec le plan JSON
Prérequis
Section intitulée « Prérequis »- Ressources et attributs (déclarer des ressources Terraform)
- Dépendances explicites (depends_on en Terraform)
- Terraform 1.15.x, la série stable courante
Qu'est-ce que le bloc lifecycle ?
Section intitulée « Qu'est-ce que le bloc lifecycle ? »C'est un bloc imbriqué, écrit à l'intérieur d'une ressource, qui modifie la manière dont Terraform planifie les opérations sur cette ressource. Il ne crée rien et ne configure aucun attribut du fournisseur : il agit sur le comportement de Terraform lui-même.
resource "local_file" "exemple" { filename = "${path.module}/exemple.txt" content = "bonjour"
lifecycle { create_before_destroy = true }}Un seul bloc lifecycle par ressource suffit : il peut contenir plusieurs
règles à la fois. Il ne peut pas vivre en dehors d'un bloc resource, data ou
ephemeral : il n'existe pas de fichier lifecycle.tf autonome.
Les sept règles
Section intitulée « Les sept règles »On cite couramment quatre règles. Le bloc en accepte sept, et les trois oubliées sont précisément celles qui intéressent un profil confirmé.
| Règle | Type | Rôle |
|---|---|---|
create_before_destroy | booléen | Inverse l'ordre du remplacement : créer, puis détruire |
prevent_destroy | booléen | Rejette tout plan qui détruirait la ressource |
ignore_changes | liste d'attributs, ou all | Cesse de proposer des mises à jour sur ces attributs |
replace_triggered_by | liste de références de ressources | Remplace la ressource quand la cible bouge |
precondition | bloc | Vérifie une hypothèse avant d'évaluer la ressource |
postcondition | bloc | Vérifie une garantie après l'application |
action_trigger | bloc | Déclenche une action sur un événement du cycle de vie (1.15.x) |
Une huitième règle, destroy, existe mais n'est valide que dans un bloc
removed.
precondition et postcondition ne sont d'ailleurs pas réservées aux
ressources gérées : elles s'écrivent aussi dans un bloc data et dans un bloc
ephemeral.
Une contrainte commune : seulement des valeurs littérales
Section intitulée « Une contrainte commune : seulement des valeurs littérales »Aucune règle du bloc n'accepte d'expression. La documentation en donne la
raison : « All lifecycle settings affect how Terraform constructs and
traverses the dependency graph. As a result, only literal values can be used
because the processing happens too early for arbitrary expression evaluation. »
Le graphe se construit avant que les expressions ne soient évaluées. Rendre une protection configurable est donc impossible :
lifecycle { prevent_destroy = var.protege # refusé}Error: Variables not allowedVariables may not be used here.
Error: Unsuitable value typeUnsuitable value: value must be knownRetenez cette contrainte dès maintenant : elle explique la moitié des messages d'erreur du chapitre. Une protection conditionnelle se gère au niveau du module appelant, pas ici.
create_before_destroy
Section intitulée « create_before_destroy »À quoi ça sert
Section intitulée « À quoi ça sert »À supprimer la fenêtre pendant laquelle la ressource n'existe plus. Par défaut, un remplacement détruit avant de créer. Avec cette règle, Terraform crée d'abord le nouvel objet, puis détruit l'ancien.
Comment ça s'écrit
Section intitulée « Comment ça s'écrit »Une seule ligne, à l'intérieur du bloc lifecycle. Le nom du fichier dépend ici
d'une valeur qui change, ce qui force le remplacement à chaque évolution :
c'est précisément le cas où l'ordre importe.
resource "local_file" "app" { filename = "${path.module}/app-${random_pet.version.id}.txt" content = "contenu applicatif"
lifecycle { create_before_destroy = true }}Quand l'utiliser
Section intitulée « Quand l'utiliser »Dès que l'indisponibilité de l'objet a un coût : bases de données, équilibreurs de charge, certificats, volumes persistants, groupes d'instances derrière un service en production.
Comment vérifier que c'est actif
Section intitulée « Comment vérifier que c'est actif »Le plan JSON donne la réponse sans ambiguïté, là où une sortie de terminal se reformate à chaque version :
terraform plan -out=tf.planterraform show -json tf.plan | jq '.resource_changes[] | {address, actions: .change.actions}'["delete", "create"]: ordre par défaut, la règle n'est pas active["create", "delete"]: la règle est active
Le piège : le sens de la propagation
Section intitulée « Le piège : le sens de la propagation »La règle se propage vers les dépendances de la ressource qui la porte, pas vers ses dépendants. C'est le point que la plupart des ressources francophones inversent.
La documentation officielle dit : « Terraform propagates and applies
create_before_destroy behavior to all resource dependencies », et
l'illustre ainsi : « create_before_destroy is enabled on resource A but not
on resource B. Because resource A is dependent on resource B, Terraform
enables create_before_destroy for resource B implicitly by default. »
Si A dépend de B et que vous posez la règle sur A, c'est B qui
l'hérite. C'est logique dès qu'on raisonne en graphe : pour créer le nouveau A
avant de détruire l'ancien, le nouveau B dont il dépend doit déjà exister.
Vérifié sur 1.15.4 : dans l'exemple ci-dessus, où local_file.app dépend de
random_pet.version, le plan montre ["create", "delete"] sur les deux,
alors que rien n'est écrit sur random_pet.version.
Deux effets de bord
Section intitulée « Deux effets de bord »L'héritage ne se refuse pas. Une dépendance qui a reçu la règle
implicitement ne peut pas la désactiver : « you cannot override
create_before_destroy to false on resource B because that would imply
dependency cycles in the graph ».
Les provisioners de destruction ne s'exécutent plus. « When the resource
contains a provisioner that runs during the destroy operation, setting
create_before_destroy to true also prevents the provisioner from running. »
Si vous comptiez sur un provisioner en when = destroy pour désenregistrer un
nœud, il ne partira plus.
prevent_destroy
Section intitulée « prevent_destroy »À quoi ça sert
Section intitulée « À quoi ça sert »À faire échouer le plan avant qu'une destruction ne soit tentée. Rien n'est lancé, rien n'est détruit : c'est un garde-fou au moment de la planification.
Comment ça s'écrit
Section intitulée « Comment ça s'écrit »resource "local_file" "donnees" { filename = "${path.module}/donnees.txt" content = "donnee critique"
lifecycle { prevent_destroy = true }}Un terraform destroy produit alors :
Error: Instance cannot be destroyed
Resource local_file.donnees has lifecycle.prevent_destroy set, but the plancalls for this resource to be destroyed. To avoid this error and continuewith the plan, either disable lifecycle.prevent_destroy or reduce the scopeof the plan using the -target option.Quand l'utiliser
Section intitulée « Quand l'utiliser »Sur les objets dont la perte est irréversible : bases de production, volumes de données, buckets d'archives, zones DNS racines.
Comment lever la protection volontairement
Section intitulée « Comment lever la protection volontairement »Passez la valeur à false, puis lancez directement terraform destroy. Aucun
apply intermédiaire n'est nécessaire : la règle n'étant pas enregistrée dans
l'état, elle est relue depuis la configuration à chaque plan.
Le piège : supprimer le bloc contourne la protection
Section intitulée « Le piège : supprimer le bloc contourne la protection »prevent_destroy ne protège pas une ressource dont vous supprimez le bloc
resource. C'est documenté, et c'est la chose la plus importante à retenir
sur cette règle : « This rule doesn't prevent Terraform from destroying a
resource if you remove its configuration. »
La cause tient en une phrase : « Except for create_before_destroy, Terraform
does not explicitly record a resource's lifecycle rule to state. As a result,
Terraform destroys the actual infrastructure during an apply operation if you
remove the resource's configuration, even if prevent_destroy is enabled. »
La règle n'existe que dans la configuration. Pas de bloc, pas de règle, pas de protection. Un collègue qui supprime dix lignes de HCL emporte la donnée avec elles, et le plan ne proteste pas.
Comment retirer une ressource sans la détruire
Section intitulée « Comment retirer une ressource sans la détruire »Avec un bloc removed portant lifecycle { destroy = false }. C'est la
manœuvre qui répond au trou décrit ci-dessus, et elle est préférée à
terraform state rm parce qu'elle passe par un plan, donc par une revue.
removed { from = local_file.donnees
lifecycle { destroy = false }}Le défaut d'un bloc removed est de détruire. Vérifié sur v1.15.4, sur les
trois écritures possibles :
| Écriture | actions du plan | Objet réel après apply |
|---|---|---|
removed sans bloc lifecycle | ["delete"] | détruit |
removed avec un lifecycle {} vide | ["delete"] | détruit |
removed avec lifecycle { destroy = false } | ["forget"] | conservé |
Ni le bloc lifecycle ni l'argument destroy ne sont obligatoires : les
omettre est parfaitement valide, et c'est ce qui rend l'erreur silencieuse.
L'action forget est la seule qui prouve, dans le plan JSON, que l'objet sera
oublié plutôt que supprimé.
Le bloc removed a ses propres règles au-delà de cet argument : il refuse une
clé d'instance, couvre un module entier, et accepte des provisioners de
destruction. Elles sont traitées dans le guide dédié,
le bloc removed.
ignore_changes
Section intitulée « ignore_changes »À quoi ça sert
Section intitulée « À quoi ça sert »À cesser de proposer des mises à jour sur certains attributs, typiquement ceux qu'un outil externe pilote : un autoscaler qui ajuste une taille, une autre équipe qui pose des tags, un opérateur qui modifie une image.
Comment ça s'écrit
Section intitulée « Comment ça s'écrit »resource "local_file" "journal" { filename = "${path.module}/journal.txt" content = var.message file_permission = var.permissions
lifecycle { ignore_changes = [content] }}Notez la syntaxe : [content], sans guillemets. Ce sont des références
d'attributs, pas des chaînes de caractères.
Avec cette configuration, terraform plan -var 'message=v2' ne propose plus
rien sur cette ressource. En revanche terraform plan -var 'permissions=0600'
propose bien un changement : la portée est limitée à l'attribut nommé.
Quand l'utiliser
Section intitulée « Quand l'utiliser »Quand la source de vérité d'un attribut est ailleurs que dans votre code, et que vous acceptez cette délégation. C'est un aveu explicite de partage de responsabilité, pas un moyen de faire taire un plan gênant.
Le piège : ce que la règle compare
Section intitulée « Le piège : ce que la règle compare »ignore_changes compare la configuration à l'état, jamais l'état au monde
réel. Une modification faite à la main sur l'objet n'est donc pas absorbée par
cette règle : elle relève de la dérive détectée au rafraîchissement, que
ignore_changes ne masque pas.
C'est la confusion la plus fréquente sur le sujet, et elle mène à des configurations qui semblent inertes puis se réveillent brutalement.
Deux limites à connaître
Section intitulée « Deux limites à connaître »Le raccourci all est plus étroit que sa réputation. « Terraform can
create and destroy the remote object but will never propose updates to it. »
La création et la destruction restent planifiées ; seules les mises à jour
disparaissent. Dire que « Terraform ne planifie plus rien » est faux.
On ne peut pas viser un meta-argument. « Terraform only ignores attributes
defined by the resource type. You can't apply ignore_changes to itself or to
any other meta-arguments. » Écrire ignore_changes = [lifecycle] donne
Error: Unsupported attribute.
replace_triggered_by
Section intitulée « replace_triggered_by »À quoi ça sert
Section intitulée « À quoi ça sert »À forcer le remplacement d'une ressource quand une autre bouge, alors même qu'aucun de ses propres attributs ne change. Le cas classique est le redémarrage d'une machine quand sa configuration évolue.
Comment ça s'écrit
Section intitulée « Comment ça s'écrit »resource "terraform_data" "declencheur" { input = var.revision}
resource "local_file" "marqueur" { filename = "${path.module}/marqueur.txt" content = "marqueur"
lifecycle { replace_triggered_by = [terraform_data.declencheur] }}Le plan produit alors, pour local_file.marqueur, actions: ["delete", "create"] et surtout action_reason: "replace_by_triggers". Cette valeur est
la seule qui prouve un replace_triggered_by : une autre trahirait un
remplacement venu d'un changement d'attribut.
Quand l'utiliser
Section intitulée « Quand l'utiliser »Quand une dépendance existe dans les faits mais pas dans les données : une VM qui doit redémarrer après un changement de configuration, un cache à vider après un déploiement, un service à recycler quand un secret tourne.
Le piège : seules les ressources gérées sont acceptées
Section intitulée « Le piège : seules les ressources gérées sont acceptées »Une variable ou un local sont refusés. « You can only reference managed
resources in replace_triggered_by expressions », et « Plain values, such as
local values and input variables, aren't valid ».
lifecycle { replace_triggered_by = [var.revision] # refusé}Error: Invalid reference in replace_triggered_by expressionOnly resources, count.index, and each.key may be used in replace_triggered_by.D'où le motif de production illustré plus haut : terraform_data, une
ressource intégrée qui ne nécessite aucun fournisseur, porte la valeur dans son
argument input et devient une adresse référençable.
Une portée plus large qu'on ne l'attend
Section intitulée « Une portée plus large qu'on ne l'attend »Le déclenchement se produit sur une mise à jour comme sur un remplacement : « If the reference is to a single resource instance, a plan to update or replace that instance triggers a replacement. » Une simple modification en place de la cible suffit donc, ce qui peut provoquer des remplacements en cascade.
Enfin, count.index et each.key sont admis : ils permettent de cibler
l'instance homologue d'une autre ressource indexée plutôt que la ressource
entière.
precondition et postcondition
Section intitulée « precondition et postcondition »À quoi ça servent
Section intitulée « À quoi ça servent »À valider des hypothèses avec les valeurs résolues au moment du plan. C'est
ce qui les distingue d'un bloc validation, qui ne voit qu'une variable
d'entrée isolée.
preconditionvérifie une hypothèse avant que la ressource ne soit évaluée : « cette combinaison de valeurs a-t-elle du sens ? »postconditionvérifie une garantie après l'application : « le résultat est-il conforme à ce que j'attendais ? »
Comment ça s'écrit
Section intitulée « Comment ça s'écrit »Les deux blocs prennent une condition et un message d'erreur. La
precondition vérifie une hypothèse avant l'action, la postcondition contrôle
le résultat après. Seule la seconde peut lire self.
resource "local_file" "app" { filename = "${path.module}/app.txt" content = replace(data.local_file.modele.content, "{{env}}", var.env)
lifecycle { precondition { condition = contains(["dev", "staging", "prod"], var.env) error_message = "env doit valoir dev, staging ou prod." }
postcondition { condition = !strcontains(self.content, "{{env}}") error_message = "Le jeton {{env}} n'a pas été substitué." } }}Quand les utiliser
Section intitulée « Quand les utiliser »Quand le contrôle porte sur plusieurs valeurs à la fois, sur un calcul
intermédiaire, ou sur un attribut que seul le fournisseur connaît. Un bloc
validation ne sait faire aucun des trois.
Quatre points à retenir
Section intitulée « Quatre points à retenir »self n'existe que dans une postcondition. Il désigne l'objet tel qu'il
vient d'être appliqué, ce qui permet de vérifier un attribut calculé, par
exemple self.public_dns != "".
L'ordre d'évaluation est précis. « Terraform evaluates precondition blocks
before evaluating the resource's configuration arguments », et la précondition
« can take precedence over argument evaluation errors ». Elle est en revanche
évaluée après count et for_each, ce qui rend each.key et count.index
disponibles dans la condition.
Terraform enregistre leur résultat, pas leur contenu. C'est ce qui alimente
le tableau checks de terraform show -json, et permet de savoir où un
contrôle a réellement été posé : kind: resource pour une précondition ou une
postcondition, kind: var pour un bloc validation.
Ne dupliquez pas la même condition sur un bloc resource et sur le bloc
data qui représente le même objet : Terraform risque alors d'ignorer les
changements du bloc data.
Le sujet est traité en détail dans valider les entrées d'une configuration Terraform.
action_trigger
Section intitulée « action_trigger »action_trigger est la règle la plus récente du bloc, documentée en 1.15.x.
Elle associe des actions à des événements du cycle de vie, choisis parmi
before_create, after_create, before_update et after_update, avec une
condition facultative.
Elle répond aux besoins qui poussaient historiquement vers les provisioner,
en restant dans le plan plutôt qu'en s'exécutant en marge.
Comment prouver un comportement du cycle de vie ?
Section intitulée « Comment prouver un comportement du cycle de vie ? »En lisant le plan converti en JSON, jamais la sortie humaine. Trois champs suffisent à tout démontrer :
| Champ | Où le lire | Ce qu'il prouve |
|---|---|---|
resource_changes[].change.actions | terraform show -json tf.plan | L'ordre : ["delete","create"] par défaut, ["create","delete"] avec create_before_destroy |
resource_changes[].action_reason | idem | La cause : replace_by_triggers prouve un replace_triggered_by |
checks[].address.kind | terraform show -json | Le niveau : resource pour une précondition, var pour une validation |
terraform plan -out=tf.planterraform show -json tf.plan | jq '.resource_changes[] | select(.change.actions != ["no-op"])'Récapitulatif
Section intitulée « Récapitulatif »Le tableau ci-dessous sert de mémo de relecture : la colonne de droite
rappelle, pour chaque règle, le comportement qui ne se devine pas. Si une seule
colonne doit être relue avant d'écrire un bloc lifecycle, c'est celle-là.
| Règle | Effet | Piège principal |
|---|---|---|
create_before_destroy | Créer avant détruire | Se propage vers les dépendances, pas les dépendants |
prevent_destroy | Rejette le plan de destruction | Contourné si on supprime le bloc resource |
ignore_changes | Cesse de proposer des mises à jour | Compare la configuration à l'état, pas le monde réel |
replace_triggered_by | Remplace sur mouvement d'une cible | Refuse variables et locals : passer par terraform_data |
precondition | Vérifie avant évaluation | Évaluée après count et for_each |
postcondition | Vérifie après application | Seul endroit où self existe |
action_trigger | Déclenche une action sur événement | Nouveauté 1.15.x |
À retenir
Section intitulée « À retenir »- Le bloc
lifecyclen'accepte que des valeurs littérales : il sert à construire le graphe de dépendances, avant toute évaluation d'expression. create_before_destroyse propage vers les dépendances, pas vers les dépendants, et cet héritage ne peut pas être refusé.prevent_destroyne protège pas contre la suppression du blocresource: la règle n'est pas enregistrée dans l'état.- Retirer une ressource sans détruire l'objet demande un bloc
removedavecdestroy = false, faute de quoi il détruit en silence. ignore_changescompare la configuration à l'état, jamais l'état au monde réel : une modification externe reste une dérive.replace_triggered_byn'accepte que des ressources gérées,count.indexeteach.key: passer parterraform_datapour une variable.- Seule la
postconditiondispose deself, puisqu'elle s'évalue après l'action. - Le plan au format JSON tranche tous ces comportements :
resource_changes[].change.actionsdit ce que Terraform va réellement faire.
Dépannage
Section intitulée « Dépannage »Messages relevés sur Terraform v1.15.4.
| Message | Cause | Solution |
|---|---|---|
Instance cannot be destroyed | prevent_destroy = true actif | Passer à false, puis terraform destroy directement : aucun apply intermédiaire n'est requis |
Variables not allowed + Unsuitable value: value must be known | Une expression dans le bloc lifecycle | Le bloc n'accepte que des littéraux : déplacer la logique dans le module appelant |
Only resources, count.index, and each.key may be used in replace_triggered_by | Un var.x ou un local.x dans replace_triggered_by | Porter la valeur avec terraform_data et référencer la ressource |
Unsupported attribute sur ignore_changes | Un meta-argument dans la liste | ignore_changes ne vise que les attributs du type de ressource |
| Plan vide alors qu'une variable a changé | L'attribut est dans ignore_changes | Vérifier la liste, et se méfier de all qui masque toutes les mises à jour |
| Remplacement en cascade inattendu | replace_triggered_by se déclenche aussi sur une mise à jour de la cible | Cibler une instance précise, ou un terraform_data dédié |
| Conflit de nom lors d'un remplacement | create_before_destroy fait coexister les deux objets | Rendre le nom variable, par exemple avec un suffixe de révision |
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous portent sur les points où le comportement observé surprend : le sens de la propagation, ce qu'une protection ne protège pas, et ce qu'une règle compare réellement. Chaque réponse indique comment le vérifier sur votre propre configuration.
Où il vit
À l'intérieur d'un blocresource, data ou ephemeral. Il ne peut pas exister seul : il n'y a pas de fichier lifecycle.tf autonome. Un seul bloc par ressource suffit, il accepte plusieurs règles à la fois.Les sept règles
| Règle | Type |
|---|---|
create_before_destroy |
booléen |
prevent_destroy |
booléen |
ignore_changes |
liste d'attributs, ou all |
replace_triggered_by |
liste de références de ressources |
precondition |
bloc |
postcondition |
bloc |
action_trigger |
bloc, Terraform 1.15.x |
destroy, n'est valide que dans un bloc removed, pas dans un bloc resource.La réponse est non
lifecycle {
prevent_destroy = var.protege # refusé
}
Error: Variables not allowed
Variables may not be used here.
La raison
La documentation officielle l'énonce ainsi : « Alllifecycle settings affect how Terraform constructs and traverses the dependency graph. As a result, only literal values can be used because the processing happens too early for arbitrary expression evaluation. »Le graphe se construit avant que les expressions soient évaluées.La conséquence
Une protection conditionnelle se gère au niveau du module appelant, pas dans le bloclifecycle. Il n'existe pas de contournement propre.Le sens est contre-intuitif
Terraform applique la règle à toutes les dépendances de la ressource qui la porte, pas à celles qui dépendent d'elle.SiA dépend de B et que vous posez create_before_destroy sur A, c'est B qui l'hérite implicitement.On ne peut pas refuser l'héritage
Forcer la valeur àfalse sur une dépendance qui a reçu la règle impliquerait un cycle dans le graphe, ce que Terraform refuse.Comment le vérifier
Le plan au format JSON tranche, plutôt que de s'en remettre à l'intuition :terraform plan -out=tfplan && terraform show -json tfplan | jq '.resource_changes[].change.actions'
Ce qu'il bloque
Unterraform destroy échoue avant toute action :Error: Instance cannot be destroyed
Resource has lifecycle.prevent_destroy set, but the plan calls for this
resource to be destroyed.
Ce qu'il ne bloque pas
La suppression du blocresource lui-même. La règle n'est pas enregistrée dans l'état : elle disparaît avec la configuration, et la ressource devient destructible au plan suivant.C'est une protection contre l'erreur de manipulation, pas contre une modification délibérée du code.Retirer une ressource sans la détruire
removed {
from = local_file.rapport
lifecycle { destroy = false }
}
Sans destroy = false, le bloc removed détruit. Le plan JSON tranche : ["forget"] conserve l'objet, ["delete"] le supprime.Ce que la règle compare
ignore_changes compare la configuration à l'état enregistré. Il n'inspecte jamais l'objet réel.La conséquence
Une modification faite directement sur le serveur est une dérive, détectée au rafraîchissement. Elle n'est pas concernée parignore_changes, qui ne fait que taire les écarts venant du code.Deux limites supplémentaires
- La règle n'accepte que des attributs de premier niveau de la ressource, pas une expression arbitraire.
- Le raccourci
allignore toute modification de configuration, ce qui gèle la ressource et masque les évolutions volontaires.
La contrainte
lifecycle {
replace_triggered_by = [var.revision] # refusé
}
Seules sont acceptées : les références à une ressource gérée, count.index et each.key. Une variable ou un local sont des valeurs simples, pas des objets suivis dans l'état.La parade
resource "terraform_data" "declencheur" {
input = var.revision
}
resource "local_file" "rapport" {
filename = "rapport.txt"
content = "contenu"
lifecycle {
replace_triggered_by = [terraform_data.declencheur]
}
}
terraform_data est une ressource intégrée dont le seul rôle est de porter une valeur dans l'état. Quand input change, la ressource change, et le remplacement se déclenche.Trois portées distinctes
| Mécanisme | Où il vit | Ce qu'il voit |
|---|---|---|
validation |
bloc variable |
la variable seule |
precondition |
lifecycle d'une ressource |
les valeurs résolues, avant l'action |
postcondition |
lifecycle d'une ressource |
les valeurs résolues, après l'action |
Le point qui les distingue vraiment
Seule lapostcondition dispose de self, puisqu'elle s'évalue après la création. Une precondition qui référence self est refusée :Error: Invalid "self" reference
The "self" object is not available in this context.
À savoir sur le moment d'évaluation
precondition et postcondition sont évaluées après count et for_each : elles voient donc une instance précise, pas la collection.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Le bloc removed : Sort une ressource du state sans la détruire, complément de
prevent_destroy. - Diagnostiquer le state : Relie
ignore_changesà la dérive détectée parplan -refresh-only. - Quiz Écrire du code Terraform : Vérifie les acquis de la section, meta-arguments compris.