Aller au contenu

TP 24 : Refactoriser sans recréer avec moved

À l’issue de ce TP, vous serez capable de :

  • comprendre pourquoi un simple renommage détruit et recrée une ressource ;
  • utiliser le bloc moved pour renommer une ressource sans impact ;
  • déplacer une ressource dans un module avec moved ;
  • valider qu’un plan ne propose ni destruction ni recréation.
  • Terraform >= 1.1 (le bloc moved est disponible depuis la 1.1).
  • Un compte AWS et la CLI aws configurée, ou l’usage du provider random pour un TP sans coût.

L’équipe d’InfraBank fait évoluer sa nomenclature : les ressources historiques doivent adopter des noms explicites, et une partie du code doit passer dans un module réutilisable. Le refactoring ne doit provoquer aucune destruction en production.

Pour rester sans coût, on travaille avec le provider random, dont le principe (destruction = recréation à l’identique) illustre parfaitement le problème.

versions.tf
terraform {
required_version = ">= 1.1"
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
}
}
main.tf
resource "random_password" "db" {
length = 20
special = true
}
Fenêtre de terminal
terraform init
terraform apply -auto-approve
terraform state list
# random_password.db

Notez la valeur générée :

Fenêtre de terminal
terraform output -raw db_secret 2>/dev/null || terraform show | grep -A2 random_password

Renommez la ressource db en database_master sans bloc moved :

resource "random_password" "database_master" {
length = 20
special = true
}
Fenêtre de terminal
terraform plan

Le plan propose :

Plan: 1 to add, 0 to change, 1 to destroy.

Terraform ne « voit » pas un renommage : il voit une adresse disparue (random_password.db) et une nouvelle (random_password.database_master). Sur une vraie ressource, cela signifierait une destruction. N’appliquez pas.

Ajoutez un bloc moved qui déclare l’équivalence entre l’ancienne et la nouvelle adresse :

moved.tf
moved {
from = random_password.db
to = random_password.database_master
}
Fenêtre de terminal
terraform plan

Le plan devient :

Plan: 0 to add, 0 to change, 0 to destroy.
# random_password.db has moved to random_password.database_master

Aucune destruction. Terraform met simplement à jour l’adresse dans le state.

Fenêtre de terminal
terraform apply -auto-approve
terraform state list
# random_password.database_master

Créez un module local qui portera désormais la ressource :

modules/secrets/versions.tf
terraform {
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
}
}
modules/secrets/main.tf
resource "random_password" "database_master" {
length = 20
special = true
}

Dans la configuration racine, remplacez la ressource par un appel de module et déclarez le déplacement :

main.tf
module "secrets" {
source = "./modules/secrets"
}
moved {
from = random_password.database_master
to = module.secrets.random_password.database_master
}
Fenêtre de terminal
terraform init # nécessaire : nouveau module
terraform plan
# random_password.database_master has moved to
# module.secrets.random_password.database_master
# Plan: 0 to add, 0 to change, 0 to destroy.
terraform apply -auto-approve
Fenêtre de terminal
terraform state list
# module.secrets.random_password.database_master
terraform plan
# No changes.

La valeur du mot de passe n’a pas changé entre les étapes : la preuve que rien n’a été recréé.

Les blocs moved peuvent rester dans le code : ils sont sans effet une fois le déplacement absorbé par tous les states. Retirez-les seulement lorsque vous êtes certain que tous les environnements ont été appliqués (sinon un environnement en retard recréerait la ressource).

  • Aucun plan de ce TP n’a proposé de destruction après ajout du bloc moved.
  • La ressource finale vit dans module.secrets.
  • La valeur générée est restée identique du début à la fin.
Fenêtre de terminal
terraform destroy -auto-approve