
Référence centrée sur la vitesse d’exécution en lab. L’examen Professional est 100% pratique : vous écrivez du HCL, vous exécutez des commandes et vous résolvez des problèmes réels. Cette page couvre les commandes avancées organisées par objectif d’examen.
Tableau “besoin → commande”
Section intitulée « Tableau “besoin → commande” »| Besoin | Commande |
|---|---|
| Importer une ressource existante | terraform import <addr> <id> |
| Renommer une ressource (déclaratif) | Bloc moved {} |
| Forcer la recréation | terraform apply -replace=<addr> |
| Lister les ressources du state | terraform state list |
| Inspecter une ressource | terraform state show <addr> |
| Déplacer dans le state | terraform state mv <old> <new> |
| Retirer du state sans détruire | terraform state rm <addr> |
| Exécuter les tests | terraform test |
| Sauvegarder un plan | terraform plan -out=tfplan |
| Appliquer un plan sauvegardé | terraform apply tfplan |
| Réconcilier le state (changements hors Terraform) | terraform plan -refresh-only |
| Mettre à jour les providers | terraform init -upgrade |
| Debug avancé | TF_LOG=TRACE terraform plan |
| Voir les providers requis | terraform providers |
| Voir les versions Terraform + providers installés | terraform version |
| Mettre à jour / préremplir le lock file | terraform providers lock |
| Lire le lock file | Ouvrir .terraform.lock.hcl |
| Afficher un output sensible | terraform output -raw <name> |
Objectif 1 — Manage resource lifecycle
Section intitulée « Objectif 1 — Manage resource lifecycle »Import d’une ressource existante
Section intitulée « Import d’une ressource existante »# Import classique (CLI)terraform import aws_instance.web i-0abc123def456
# Import avec adresse de moduleterraform import module.vpc.aws_vpc.main vpc-0abc123Bloc import (déclaratif — Terraform 1.5+) :
import { to = aws_instance.web id = "i-0abc123def456"}# Générer le code HCL automatiquementterraform plan -generate-config-out=generated_resources.tfBloc moved (refactoring)
Section intitulée « Bloc moved (refactoring) »# Renommer une ressourcemoved { from = aws_instance.web to = aws_instance.application}
# Déplacer dans un modulemoved { from = aws_instance.web to = module.compute.aws_instance.main}
# Renommer un modulemoved { from = module.old_name to = module.new_name}Vérification :
# Le plan doit montrer "moved" sans create/destroyterraform plan# → aws_instance.application has moved from aws_instance.webManipulation du state
Section intitulée « Manipulation du state »# Lister toutes les ressourcesterraform state list
# Filtrer par adresseterraform state list module.vpc
# Inspecter une ressource en détailterraform state show aws_instance.web
# Déplacer (opération manuelle ponctuelle)terraform state mv aws_instance.web aws_instance.applicationterraform state mv aws_instance.web module.compute.aws_instance.main
# Retirer du state (la ressource reste dans AWS)terraform state rm aws_instance.legacy
# Télécharger le state distant en JSONterraform state pull
# Envoyer un state local vers le backendterraform state push terraform.tfstateRecréation forcée
Section intitulée « Recréation forcée »# Forcer la destruction + recréation d'une ressourceterraform apply -replace=aws_instance.web
# Avec un plan sauvegardéterraform plan -replace=aws_instance.web -out=tfplanterraform apply tfplanOptions avancées de plan et apply
Section intitulée « Options avancées de plan et apply »# Plan avec cible spécifiqueterraform plan -target=module.vpc
# Plan de destructionterraform plan -destroy
# Apply sans interaction (CI/CD)terraform apply -input=false -auto-approve
# Refresh only (réconcilier le state avec l'infrastructure réelle)terraform apply -refresh-only -auto-approve
# Parallélisme (par défaut : 10)terraform apply -parallelism=20Provisioners (dernier recours)
Section intitulée « Provisioners (dernier recours) »resource "aws_instance" "web" { ami = data.aws_ami.ubuntu.id instance_type = "t3.micro"
# Exécution locale après création provisioner "local-exec" { command = "echo ${self.private_ip} >> hosts.txt" }
# Exécution distante provisioner "remote-exec" { inline = [ "sudo apt-get update", "sudo apt-get install -y nginx" ]
connection { type = "ssh" user = "ubuntu" private_key = file("~/.ssh/id_rsa") host = self.public_ip } }
# Exécution à la destruction provisioner "local-exec" { when = destroy command = "echo 'Instance destroyed'" }}Objectif 2 — Dynamic configuration
Section intitulée « Objectif 2 — Dynamic configuration »Preconditions et postconditions
Section intitulée « Preconditions et postconditions »resource "aws_instance" "web" { ami = var.ami_id instance_type = var.instance_type
lifecycle { # Vérification AVANT la création precondition { condition = can(regex("^ami-", var.ami_id)) error_message = "L'AMI doit commencer par 'ami-'." }
# Vérification APRÈS la création postcondition { condition = self.public_ip != "" error_message = "L'instance doit avoir une IP publique." } }}Check blocks
Section intitulée « Check blocks »check "website_health" { data "http" "app" { url = "https://${aws_lb.main.dns_name}/health" }
assert { condition = data.http.app.status_code == 200 error_message = "Le site ne répond pas correctement." }}terraform test
Section intitulée « terraform test »variables { instance_type = "t3.micro" environment = "test"}
run "create_instance" { command = apply
assert { condition = aws_instance.web.instance_type == "t3.micro" error_message = "Mauvais type d'instance." }
assert { condition = aws_instance.web.tags["Environment"] == "test" error_message = "Tag Environment incorrect." }}
run "verify_plan_only" { command = plan
assert { condition = aws_instance.web.ami != "" error_message = "AMI non définie." }}# Exécuter les teststerraform test
# Tests verbeuxterraform test -verbose
# Filtre sur un fichier de testterraform test -filter=tests/main.tftest.hclDynamic blocks
Section intitulée « Dynamic blocks »variable "ingress_rules" { type = list(object({ port = number protocol = string cidr_blocks = list(string) })) default = [ { port = 80, protocol = "tcp", cidr_blocks = ["0.0.0.0/0"] }, { port = 443, protocol = "tcp", cidr_blocks = ["0.0.0.0/0"] }, ]}
resource "aws_security_group" "web" { name = "web-sg"
dynamic "ingress" { for_each = var.ingress_rules content { from_port = ingress.value.port to_port = ingress.value.port protocol = ingress.value.protocol cidr_blocks = ingress.value.cidr_blocks } }}Fonctions avancées
Section intitulée « Fonctions avancées »# flatten : aplatir des listes imbriquéeslocals { all_subnets = flatten([ for env, config in var.environments : [ for subnet in config.subnets : { env = env cidr = subnet } ] ])}
# setproduct : produit cartésienlocals { az_subnet_pairs = setproduct(var.azs, var.subnet_cidrs)}
# cidrsubnet : calcul de sous-réseauxlocals { subnets = [for i in range(3) : cidrsubnet("10.0.0.0/16", 8, i)] # → ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]}
# templatefile : template avec variablesresource "aws_instance" "web" { user_data = templatefile("${path.module}/user-data.tpl", { hostname = var.hostname packages = join(" ", var.packages) })}
# try et can : gestion d'erreurslocals { name = try(var.config.name, "default") is_valid = can(regex("^[a-z]+$", var.input))}Types complexes et optional
Section intitulée « Types complexes et optional »variable "server_config" { type = object({ name = string instance_type = optional(string, "t3.micro") tags = optional(map(string), {}) monitoring = optional(object({ enabled = bool interval = optional(number, 60) }), { enabled = false }) })}Objectif 3 — Collaborative workflows
Section intitulée « Objectif 3 — Collaborative workflows »Backend S3 avec locking DynamoDB
Section intitulée « Backend S3 avec locking DynamoDB »terraform { backend "s3" { bucket = "my-terraform-state" key = "production/terraform.tfstate" region = "eu-west-1" dynamodb_table = "terraform-locks" encrypt = true }}Remote state (lecture)
Section intitulée « Remote state (lecture) »# Lire le state d'une autre configurationdata "terraform_remote_state" "vpc" { backend = "s3" config = { bucket = "my-terraform-state" key = "network/terraform.tfstate" region = "eu-west-1" }}
# Utiliser les outputsresource "aws_instance" "web" { subnet_id = data.terraform_remote_state.vpc.outputs.private_subnet_ids[0]}tfe_outputs (alternative HCP Terraform)
Section intitulée « tfe_outputs (alternative HCP Terraform) »# Lire les outputs d'un workspace HCP Terraformdata "tfe_outputs" "network" { config = { organization = "my-org" workspaces = { name = "network-prod" } }}
resource "aws_instance" "web" { subnet_id = data.tfe_outputs.network.outputs.subnet_id}Version constraints
Section intitulée « Version constraints »terraform { required_version = ">= 1.6.0, < 2.0.0"
required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }}Syntaxe des contraintes :
| Opérateur | Signification | Exemple |
|---|---|---|
= | Exactement | = "5.0.0" |
!= | Pas cette version | != "5.1.0" |
>, >=, <, <= | Comparaison | >= 5.0 |
~> | Pessimistic (incrémente le dernier chiffre) | ~> 5.0 → >= 5.0, < 6.0 |
Automatisation CI/CD
Section intitulée « Automatisation CI/CD »# Pipeline type : plan séparé de l'apply# Étape 1 : Planterraform init -input=falseterraform plan -input=false -out=tfplan
# Étape 2 : Apply (après approbation)terraform apply -input=false tfplanObjectif 4 — Modules
Section intitulée « Objectif 4 — Modules »Structure standard d’un module
Section intitulée « Structure standard d’un module »modules/└── compute/ ├── main.tf # Ressources ├── variables.tf # Inputs ├── outputs.tf # Outputs ├── versions.tf # Required providers ├── README.md # Documentation └── tests/ └── main.tftest.hcl # TestsPasser des providers à un module
Section intitulée « Passer des providers à un module »# Root moduleprovider "aws" { alias = "us" region = "us-east-1"}
provider "aws" { alias = "eu" region = "eu-west-1"}
module "us_infra" { source = "./modules/compute"
providers = { aws = aws.us }}
module "eu_infra" { source = "./modules/compute"
providers = { aws = aws.eu }}Refactoring : extraire en module
Section intitulée « Refactoring : extraire en module »# Étape 1 : Déplacer le code dans le module
# Étape 2 : Ajouter le bloc movedmoved { from = aws_instance.web to = module.compute.aws_instance.main}
moved { from = aws_security_group.web to = module.compute.aws_security_group.main}
# Étape 3 : Vérifier# terraform plan ne doit montrer AUCUN destroyObjectif 5 — Providers
Section intitulée « Objectif 5 — Providers »Provider aliasing multi-région
Section intitulée « Provider aliasing multi-région »provider "aws" { region = "eu-west-1" # Provider par défaut}
provider "aws" { alias = "us_east" region = "us-east-1"}
# Utilisation dans une ressourceresource "aws_s3_bucket" "backup" { provider = aws.us_east bucket = "backup-us-east"}Authentication AWS
Section intitulée « Authentication AWS »# Méthode 1 : Environment variables (recommandé en CI/CD)# export AWS_ACCESS_KEY_ID="..."# export AWS_SECRET_ACCESS_KEY="..."# export AWS_REGION="eu-west-1"
# Méthode 2 : Shared credentials fileprovider "aws" { shared_credentials_files = ["~/.aws/credentials"] profile = "production"}
# Méthode 3 : Assume roleprovider "aws" { assume_role { role_arn = "arn:aws:iam::123456789:role/terraform" session_name = "terraform-session" }}Diagnostic des erreurs de provider
Section intitulée « Diagnostic des erreurs de provider »# Version incompatibleterraform init -upgradeterraform providers
# Credentials invalidesexport TF_LOG=DEBUGterraform plan 2>&1 | grep -i "auth\|credential\|access"
# Rate limitingterraform apply -parallelism=5 # Réduire le parallélisme
# Provider lock corrompurm .terraform.lock.hclterraform initDebugging et diagnostic
Section intitulée « Debugging et diagnostic »Variables d’environnement de debug
Section intitulée « Variables d’environnement de debug »# Niveaux : TRACE > DEBUG > INFO > WARN > ERRORexport TF_LOG=TRACEexport TF_LOG_PATH=/tmp/terraform-debug.log
# Debug uniquement le providerexport TF_LOG_PROVIDER=TRACE
# Debug uniquement le coreexport TF_LOG_CORE=DEBUG
# Désactiverunset TF_LOG TF_LOG_PATH TF_LOG_PROVIDER TF_LOG_COREDiagnostic rapide en examen
Section intitulée « Diagnostic rapide en examen »# Le plan échoue ? Vérifiez dans cet ordre :# 1. Syntaxeterraform validate
# 2. Stateterraform state listterraform state show <resource>
# 3. Providerterraform providerscat .terraform.lock.hcl
# 4. Logs détaillésTF_LOG=DEBUG terraform plan 2>&1 | tail -50
# 5. Refreshterraform plan -refresh-onlyNaviguer dans la documentation (stratégie examen)
Section intitulée « Naviguer dans la documentation (stratégie examen) »La documentation est autorisée pendant le lab. Voici les pages les plus utiles :
| Besoin | Où chercher |
|---|---|
| Syntaxe d’une ressource AWS | registry.terraform.io/providers/hashicorp/aws → recherche |
| Fonctions HCL | developer.hashicorp.com/terraform/language/functions |
| Bloc lifecycle | developer.hashicorp.com/terraform/language/meta-arguments/lifecycle |
| terraform test | developer.hashicorp.com/terraform/language/tests |
| Check blocks | developer.hashicorp.com/terraform/language/checks |
| Bloc moved | developer.hashicorp.com/terraform/language/modules/develop/refactoring |
| Backend S3 | developer.hashicorp.com/terraform/language/backend/s3 |
| Provider configuration | developer.hashicorp.com/terraform/language/providers/configuration |
À retenir
Section intitulée « À retenir »- L’examen lab utilise Terraform 1.6 + AWS — entraînez-vous avec cette version
- La documentation est votre alliée — apprenez à y naviguer vite
moved {}est préféré àstate mv— apprenez les deuxterraform test(.tftest.hcl) est un sujet clé de l’objectif 2- Les preconditions/postconditions dans lifecycle sont un pattern récurrent
- Le provider aliasing multi-région est un sujet incontournable
- Les provisioners existent mais sont déconseillés — sachez quand les utiliser
- L’objectif 6 (HCP Terraform) est en QCM — pas besoin de commandes lab
Prochaines étapes
Section intitulée « Prochaines étapes » Exercices Professional Entraînement lab chronométré sur AWS
Guide de préparation Professional Plan de révision complet sur 6 semaines
Blocs dynamiques Dynamic blocks en profondeur
Tester un module terraform test et validation