Aller au contenu
Infrastructure as Code medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Exercices Professional : entraînement lab Terraform

33 min de lecture

logo terraform

27 exercices pratiques qui simulent le format lab. Chaque exercice pose un problème concret : écrire du HCL, corriger une erreur, refactorer du code. Les solutions sont masquées — essayez de résoudre chaque exercice avant de regarder la réponse.


Exercice 1 — Importer une ressource existante (déclaratif)

Section intitulée « Exercice 1 — Importer une ressource existante (déclaratif) »

Situation : Un collègue a créé un bucket S3 manuellement (my-app-logs-prod). Vous devez l’intégrer dans le code Terraform sans recréer le bucket.

Consigne : Écrivez le bloc import {} et la ressource correspondante pour que terraform plan ne montre aucun changement.

Voir la solution
import {
to = aws_s3_bucket.logs
id = "my-app-logs-prod"
}
resource "aws_s3_bucket" "logs" {
bucket = "my-app-logs-prod"
}

Vérification :

Fenêtre de terminal
terraform plan
# Plan: 1 to import, 0 to add, 0 to change, 0 to destroy
terraform apply
# aws_s3_bucket.logs: Importing... [id=my-app-logs-prod]
# Import complete!
terraform plan
# No changes. Your infrastructure matches the configuration.
# 0 to add, 0 to change, 0 to destroy

Le plan prépare l’import, mais seul l’apply l’exécute réellement. Si le plan après l’apply montre des changements, c’est que la ressource HCL ne correspond pas à l’état réel. Ajoutez les attributs manquants (tags, versioning, etc.) pour éliminer le diff.

Situation : Votre configuration contient aws_instance.web_server. Vous voulez la déplacer dans un module compute sous le nom aws_instance.main, sans détruire l’instance.

Consigne : Écrivez le bloc moved {} et l’appel de module nécessaires.

Voir la solution
# Dans le root module
moved {
from = aws_instance.web_server
to = module.compute.aws_instance.main
}
module "compute" {
source = "./modules/compute"
ami = var.ami_id
instance_type = var.instance_type
subnet_id = var.subnet_id
}
# Dans modules/compute/main.tf
resource "aws_instance" "main" {
ami = var.ami
instance_type = var.instance_type
subnet_id = var.subnet_id
}

Vérification :

Fenêtre de terminal
terraform plan
# Doit afficher :
# aws_instance.web_server has moved to module.compute.aws_instance.main
# 0 to add, 0 to change, 0 to destroy

Si le plan montre un destroy + create, le bloc moved est mal formé ou les attributs de la ressource dans le module ne correspondent pas.

Situation : Votre state contient une ressource aws_iam_role.legacy qui a été supprimée manuellement dans la console AWS. terraform plan veut la recréer. Vous avez déjà retiré le bloc resource correspondant du code.

Consigne : Quelle commande permet de supprimer l’entrée orpheline du state ?

Voir la solution
Fenêtre de terminal
# Retirer du state sans tenter de détruire dans AWS
terraform state rm aws_iam_role.legacy
# Vérifier que la ressource n'est plus dans le state
terraform state list | grep legacy
# Le plan doit maintenant être propre
terraform plan
# 0 to add, 0 to change, 0 to destroy

Ne confondez pas state rm (retire du state uniquement) avec destroy (supprime dans AWS + retire du state). Ici, la ressource n’existe plus dans AWS : on nettoie le state.

Attention : state rm ne retire l’objet que du state. Si le bloc resource est toujours présent dans le code, le plan suivant tentera de recréer la ressource. Il faut donc retirer le bloc HCL et nettoyer le state.

Situation : L’AMI de votre instance aws_instance.web a été corrompue. L’instance tourne encore mais vous devez la recréer à partir de la même AMI.

Consigne : Quelle commande force la recréation sans modifier le code HCL ?

Voir la solution
Fenêtre de terminal
# Forcer la destruction + recréation
terraform apply -replace=aws_instance.web

Le plan affichera :

# aws_instance.web must be replaced
-/+ resource "aws_instance" "web" {

L’ancienne syntaxe terraform taint est dépréciée depuis Terraform 0.15.2. Utilisez toujours -replace.

Situation : Un administrateur a modifié les tags d’une instance directement dans la console AWS. Vous voulez détecter les changements sans appliquer aucune modification.

Consigne : Quelle commande permet de mettre à jour le state avec l’état réel sans modifier l’infrastructure ?

Voir la solution
Fenêtre de terminal
# Détecter le drift : met à jour le state avec l'état réel AWS
terraform plan -refresh-only
# Appliquer la mise à jour du state (sans modifier l'infra)
terraform apply -refresh-only

Après apply -refresh-only, le state reflète l’état réel. Un terraform plan normal montrera ensuite les différences entre le code HCL et le nouvel état du state — c’est-à-dire les modifications manuelles à corriger ou à adopter.


Situation : Vous créez un module qui accepte un instance_type. Le module ne supporte que les types t3.* et t2.*.

Consigne : Ajoutez une precondition qui bloque le plan si un type non supporté est passé.

Voir la solution
variable "instance_type" {
type = string
}
resource "aws_instance" "main" {
ami = var.ami_id
instance_type = var.instance_type
lifecycle {
precondition {
condition = can(regex("^t[23]\\.", var.instance_type))
error_message = "Seuls les types t2.* et t3.* sont supportés. Reçu : ${var.instance_type}"
}
}
}

Avec instance_type = "m5.large", le plan échoue avec :

│ Error: Resource precondition failed
│ Seuls les types t2.* et t3.* sont supportés. Reçu : m5.large

Situation : Vous avez une variable ports de type list(number) contenant les ports à ouvrir. Créez un security group avec un bloc dynamic pour les règles ingress.

Consigne : Écrivez le security group avec un dynamic block qui crée une règle ingress TCP par port.

Voir la solution
variable "ports" {
type = list(number)
default = [80, 443, 8080]
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group pour le web"
vpc_id = var.vpc_id
dynamic "ingress" {
for_each = var.ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

Le bloc dynamic itère sur var.ports. L’itérateur par défaut porte le nom du bloc (ingress). Pour un nom personnalisé, ajoutez iterator = ....

Situation : Vous avez un module qui crée un bucket S3 avec le naming pattern {env}-{app}-data. Écrivez un test qui :

  • Vérifie que le bucket est créé
  • Vérifie que le nom suit le pattern attendu

Consigne : Écrivez le fichier .tftest.hcl complet.

Voir la solution
tests/bucket.tftest.hcl
variables {
environment = "test"
app_name = "myapp"
}
run "create_bucket" {
command = plan
assert {
condition = aws_s3_bucket.data.bucket == "test-myapp-data"
error_message = "Le nom du bucket ne suit pas le pattern {env}-{app}-data. Obtenu : ${aws_s3_bucket.data.bucket}"
}
assert {
condition = aws_s3_bucket.data.bucket != ""
error_message = "Le bucket ne doit pas avoir un nom vide."
}
}

Le module correspondant :

main.tf
resource "aws_s3_bucket" "data" {
bucket = "${var.environment}-${var.app_name}-data"
}
Fenêtre de terminal
terraform test
# Success! 2 passed, 0 failed.

Exercice 9 — Check block (vérification post-apply)

Section intitulée « Exercice 9 — Check block (vérification post-apply) »

Situation : Après le déploiement d’un load balancer, vous voulez vérifier que l’endpoint /health répond en 200.

Consigne : Écrivez un bloc check qui vérifie la santé du load balancer.

Voir la solution
resource "aws_lb" "main" {
name = "app-lb"
internal = false
load_balancer_type = "application"
subnets = var.public_subnet_ids
}
check "lb_health" {
data "http" "health" {
url = "http://${aws_lb.main.dns_name}/health"
}
assert {
condition = data.http.health.status_code == 200
error_message = "Le load balancer ne répond pas sur /health (code: ${data.http.health.status_code})."
}
}

Le bloc check est évalué en fin de plan et en fin d’apply. Contrairement aux postconditions, un échec de check n’annule pas l’opération — il émet un warning. C’est un mécanisme de surveillance continue, pas de validation bloquante.

Situation : Vous créez une instance EC2 qui doit obtenir une IP publique. Si l’instance est lancée dans un sous-réseau privé par erreur, vous voulez que Terraform échoue.

Consigne : Ajoutez une postcondition qui vérifie que l’instance a reçu une IP publique.

Voir la solution
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = var.subnet_id
associate_public_ip_address = true
lifecycle {
postcondition {
condition = self.public_ip != ""
error_message = "L'instance n'a pas reçu d'IP publique. Vérifiez que le sous-réseau ${var.subnet_id} est public."
}
}
}

La postcondition s’évalue après la création de la ressource. Si l’instance est créée sans IP publique, Terraform marque l’opération comme échouée et bloque les actions downstream qui dépendent de cette ressource — mais il ne rollback pas ce qui a déjà été créé. L’instance existera dans le state, avec une erreur à corriger.

Situation : Vous avez une variable qui définit des environnements avec chacun une liste de sous-réseaux :

variable "environments" {
default = {
prod = { subnets = ["10.0.1.0/24", "10.0.2.0/24"] }
dev = { subnets = ["10.1.1.0/24"] }
}
}

Consigne : Utilisez flatten et une boucle for pour créer une liste plate de tous les sous-réseaux avec leur environnement.

Voir la solution
locals {
all_subnets = flatten([
for env, config in var.environments : [
for cidr in config.subnets : {
environment = env
cidr = cidr
}
]
])
}
# Résultat :
# [
# { environment = "prod", cidr = "10.0.1.0/24" },
# { environment = "prod", cidr = "10.0.2.0/24" },
# { environment = "dev", cidr = "10.1.1.0/24" },
# ]
# Utilisation avec for_each (nécessite une map ou un set)
resource "aws_subnet" "all" {
for_each = { for s in local.all_subnets : "${s.environment}-${s.cidr}" => s }
vpc_id = var.vpc_id
cidr_block = each.value.cidr
tags = {
Environment = each.value.environment
}
}

Le pattern flatten + double for + conversion en map avec for_each est très fréquent dans l’examen.


Situation : Vous devez configurer un backend distant S3 avec verrouillage DynamoDB pour une infrastructure de production.

Consigne : Écrivez la configuration complète du backend et la table DynamoDB.

Voir la solution
backend.tf
terraform {
backend "s3" {
bucket = "mycompany-terraform-state"
key = "production/network/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
# state-infra/main.tf (à appliquer séparément, avec un backend local)
resource "aws_s3_bucket" "state" {
bucket = "mycompany-terraform-state"
}
resource "aws_s3_bucket_versioning" "state" {
bucket = aws_s3_bucket.state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_dynamodb_table" "locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}

La table DynamoDB doit avoir une clé primaire nommée LockID de type String. C’est un piège fréquent dans l’examen.

Note 2026 : le backend S3 supporte désormais le verrouillage natif via use_lockfile = true, rendant la table DynamoDB dépréciée. L’exercice conserve DynamoDB car l’examen Professional cible Terraform 1.6, où ce mécanisme est encore la norme.

Situation : L’équipe réseau a déployé un VPC avec Terraform. Ses outputs exposent vpc_id et private_subnet_ids. Vous devez lire ces outputs pour déployer vos instances.

Consigne : Écrivez le data source terraform_remote_state et utilisez les outputs.

Voir la solution
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "mycompany-terraform-state"
key = "production/network/terraform.tfstate"
region = "eu-west-1"
}
}
resource "aws_instance" "app" {
count = 2
ami = var.ami_id
instance_type = "t3.medium"
subnet_id = data.terraform_remote_state.network.outputs.private_subnet_ids[count.index]
vpc_security_group_ids = [aws_security_group.app.id]
tags = {
Name = "app-${count.index}"
}
}
resource "aws_security_group" "app" {
vpc_id = data.terraform_remote_state.network.outputs.vpc_id
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}
}

L’accès aux outputs se fait via data.terraform_remote_state.<name>.outputs.<key>. Les outputs du VPC doivent être déclarés dans la configuration réseau avec output "vpc_id" { ... } et output "private_subnet_ids" { ... }.

Situation : Votre équipe utilise le provider AWS 5.x. Vous devez empêcher toute mise à jour vers une version 6.x non testée, tout en permettant les mises à jour mineures.

Consigne : Écrivez la contrainte de version correcte.

Voir la solution
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

~> 5.0 signifie : >= 5.0.0 et < 6.0.0. C’est l’opérateur pessimistic constraint — il autorise les mises à jour de la partie la plus à droite seulement.

ContrainteAutoriseBloque
~> 5.0>= 5.0.0, < 6.0.06.0.0+
~> 5.30>= 5.30.0, < 6.0.06.0.0+
~> 5.30.0>= 5.30.0, < 5.31.05.31.0+
>= 5.0, < 5.505.0.0 → 5.49.x5.50.0+

La différence clé : ~> 5.30 a deux composants (majeur.mineur) donc le mineur peut incrémenter librement sous la même majeure ; ~> 5.30.0 a trois composants donc seul le patch peut incrémenter.


Situation : Vous gérez une infrastructure multi-région. Votre module compute doit être déployé dans eu-west-1 et us-east-1.

Consigne : Écrivez les deux appels de module avec le bon provider pour chaque région.

Voir la solution
providers.tf
provider "aws" {
region = "eu-west-1"
}
provider "aws" {
alias = "us_east"
region = "us-east-1"
}
# main.tf
module "eu_compute" {
source = "./modules/compute"
providers = {
aws = aws
}
instance_type = "t3.medium"
environment = "production"
}
module "us_compute" {
source = "./modules/compute"
providers = {
aws = aws.us_east
}
instance_type = "t3.medium"
environment = "production"
}
modules/compute/versions.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

Le provider par défaut (sans alias) n’a pas besoin de providers = {} dans l’appel de module. L’attribut providers est requis uniquement quand vous passez un provider avec alias.

Situation : Votre code utilise count pour créer 3 instances. Quand vous supprimez l’instance du milieu, Terraform veut recréer les instances restantes.

variable "names" {
default = ["web-1", "web-2", "web-3"]
}
resource "aws_instance" "app" {
count = length(var.names)
ami = var.ami_id
instance_type = "t3.micro"
tags = {
Name = var.names[count.index]
}
}

Consigne : Convertissez en for_each et écrivez les blocs moved nécessaires.

Voir la solution
variable "names" {
default = ["web-1", "web-2", "web-3"]
}
resource "aws_instance" "app" {
for_each = toset(var.names)
ami = var.ami_id
instance_type = "t3.micro"
tags = {
Name = each.key
}
}
# Bloc moved pour chaque instance existante
moved {
from = aws_instance.app[0]
to = aws_instance.app["web-1"]
}
moved {
from = aws_instance.app[1]
to = aws_instance.app["web-2"]
}
moved {
from = aws_instance.app[2]
to = aws_instance.app["web-3"]
}

Avec for_each, supprimer "web-2" de la liste ne touche que cette instance. C’est l’avantage principal de for_each sur count — les clés sont stables.

Situation : Votre module network crée un VPC et 3 sous-réseaux privés. Le root module a besoin du VPC ID et de la liste des subnet IDs.

Consigne : Écrivez les outputs du module et leur utilisation dans le root module.

Voir la solution
modules/network/outputs.tf
output "vpc_id" {
description = "ID du VPC créé"
value = aws_vpc.main.id
}
output "private_subnet_ids" {
description = "Liste des IDs de sous-réseaux privés"
value = [for s in aws_subnet.private : s.id]
}
output "private_subnet_cidrs" {
description = "Map subnet name → CIDR"
value = { for k, s in aws_subnet.private : k => s.cidr_block }
}
# root main.tf
module "network" {
source = "./modules/network"
vpc_cidr = "10.0.0.0/16"
subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
}
resource "aws_instance" "app" {
count = 3
subnet_id = module.network.private_subnet_ids[count.index]
tags = {
VPC = module.network.vpc_id
}
}

Les outputs de module sont accessibles via module.<name>.<output_name>. Si l’output contient des données sensibles, ajoutez sensitive = true.


Exercice 18 — Provider aliasing pour un certificat ACM

Section intitulée « Exercice 18 — Provider aliasing pour un certificat ACM »

Situation : Votre application est déployée en eu-west-1, mais les certificats ACM pour CloudFront doivent être créés dans us-east-1.

Consigne : Configurez les providers et créez le certificat dans la bonne région.

Voir la solution
provider "aws" {
region = "eu-west-1"
}
provider "aws" {
alias = "us_east"
region = "us-east-1"
}
resource "aws_acm_certificate" "cdn" {
provider = aws.us_east
domain_name = "app.example.com"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
resource "aws_cloudfront_distribution" "main" {
# Utilise le provider par défaut (eu-west-1)
# Le certificat ACM doit être dans us-east-1 pour CloudFront
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.cdn.arn
ssl_support_method = "sni-only"
}
}

C’est un pattern classique de l’examen : CloudFront exige un certificat ACM dans us-east-1, quel que soit la région de déploiement.

Situation : Vous déployez de l’infrastructure dans un compte AWS cible depuis votre compte de management. Le rôle arn:aws:iam::TARGET_ACCOUNT:role/TerraformRole est disponible.

Consigne : Configurez le provider pour assumer ce rôle.

Voir la solution
provider "aws" {
region = "eu-west-1"
assume_role {
role_arn = "arn:aws:iam::123456789012:role/TerraformRole"
session_name = "terraform-deploy"
external_id = "terraform-2026"
}
}

Terraform utilise les credentials locales (ou du CI/CD) pour faire un sts:AssumeRole vers le compte cible. Le external_id est optionnel mais recommandé pour la sécurité cross-account.

Vérification :

Fenêtre de terminal
# Avant l'assume role
aws sts get-caller-identity
# Terraform assume le rôle automatiquement lors du plan/apply
terraform plan

Situation : terraform plan échoue avec une erreur cryptique :

Error: error configuring Terraform AWS Provider: failed to get shared config profile

Consigne : Décrivez les étapes de diagnostic dans l’ordre.

Voir la solution
Fenêtre de terminal
# 1. Vérifier les credentials actuelles
aws sts get-caller-identity
# 2. Vérifier la configuration du provider
cat main.tf | grep -A 10 'provider "aws"'
# 3. Vérifier les variables d'environnement
env | grep AWS
# 4. Vérifier le profil référencé
cat ~/.aws/config
cat ~/.aws/credentials
# 5. Activer les logs détaillés
export TF_LOG=DEBUG
terraform plan 2>&1 | grep -i "profile\|credential\|auth"
# 6. Tester avec des credentials explicites
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
terraform plan

L’erreur “failed to get shared config profile” signifie que le provider référence un profil (profile = "xxx") qui n’existe pas dans ~/.aws/config ou ~/.aws/credentials. Soit le profil est mal nommé, soit le fichier credentials n’est pas au bon endroit.


Exercice 21 — Modes d’exécution HCP Terraform

Section intitulée « Exercice 21 — Modes d’exécution HCP Terraform »

Question : Dans HCP Terraform, quel mode d’exécution permet de lancer terraform plan et terraform apply sur votre machine locale tout en stockant le state dans HCP ?

A. Remote execution B. Local execution C. Agent execution D. CLI-driven execution

Voir la réponse

B. Local execution

HCP Terraform propose trois modes d’exécution (execution modes) :

Mode d’exécutionPlan/ApplyStateUsage
RemoteHCPHCPDéfaut, CI/CD
LocalMachine localeHCPDéveloppement
AgentAgent auto-hébergéHCPRéseau privé

CLI-driven n’est pas un mode d’exécution — c’est un workflow qui déclenche un run remote depuis la CLI locale (le plan/apply s’exécute sur HCP, pas en local).

Attention : en mode Local, HCP Terraform n’évalue pas les workspace variables ni les variable sets. Seules les variables définies localement (.tfvars, env, CLI) sont prises en compte.

Question : À quel moment Sentinel évalue-t-il les policies dans le workflow HCP Terraform ?

A. Avant le plan B. Après le plan, avant l’apply C. Après l’apply D. Au commit Git

Voir la réponse

B. Après le plan, avant l’apply

Le workflow HCP Terraform est :

  1. Plan — Terraform génère le plan d’exécution
  2. Policy check — Sentinel évalue les policies sur le plan
  3. Apply — Si les policies passent, l’apply est autorisé

Les policies Sentinel peuvent avoir trois niveaux :

  • advisory — Warning seulement
  • soft-mandatory — Bloquant, mais un admin peut forcer
  • hard-mandatory — Bloquant, pas de dérogation

Question : Vous avez 15 workspaces qui partagent les mêmes credentials AWS. Comment les distribuer efficacement sans dupliquer les variables ?

A. Définir les variables dans chaque workspace B. Utiliser un fichier .tfvars partagé C. Créer un variable set attaché aux workspaces D. Utiliser des environment variables sur le runner

Voir la réponse

C. Créer un variable set attaché aux workspaces

Les variable sets de HCP Terraform permettent de :

  • Définir des variables une seule fois
  • Les partager entre plusieurs workspaces ou un projet entier
  • Gérer les credentials de manière centralisée
  • Supporter les variables sensibles (valeur masquée)

Les réponses A et D fonctionnent mais ne sont pas efficaces à l’échelle. La réponse B n’est pas supportée nativement par HCP Terraform.

Question : Dans un workspace HCP Terraform configuré avec un VCS workflow, que se passe-t-il quand un pull request est ouvert ?

A. Un terraform apply est exécuté automatiquement B. Un speculative plan est exécuté et un check de statut est posté sur la PR C. Rien, il faut lancer un run manuellement D. Le workspace est verrouillé

Voir la réponse

B. Un speculative plan est exécuté et un check de statut est posté sur la PR

Le VCS workflow de HCP Terraform :

  • PR ouverteSpeculative plan (plan-only, non applicable). HCP poste un status check (et un lien vers le plan) sur la pull request.
  • Merge sur la branche par défaut → Full run (plan + apply après approbation)

C’est le workflow recommandé pour les équipes : le plan en PR permet la revue de code et la revue d’infrastructure en même temps. Le status check permet de voir directement si le plan passe ou échoue, sans quitter l’interface VCS.

Question : Le workspace network produit des outputs (VPC ID, subnet IDs) consommés par le workspace compute via terraform_remote_state. Comment déclencher automatiquement un run de compute quand network change ?

A. Webhook personnalisé B. Run trigger de network vers compute C. Variable set partagé D. API Terraform

Voir la réponse

B. Run trigger de network vers compute

Les run triggers créent une chaîne de dépendances entre workspaces. Quand le workspace source (network) termine un apply avec succès, un run est automatiquement déclenché dans le workspace destination (compute).

Configuration : dans le workspace compute, ajouter network comme source de run trigger. C’est une relation one-to-many : un workspace peut avoir plusieurs sources.

Question : Après un terraform init, le fichier .terraform.lock.hcl est créé. Quel est son rôle et que se passe-t-il si vous supprimez ce fichier puis relancez terraform init ?

A. Rien — Terraform réinstalle les mêmes versions B. Terraform installe la dernière version compatible (qui peut différer) C. Terraform refuse de s’initialiser D. Le state est corrompu

Voir la réponse

B. Terraform installe la dernière version compatible (qui peut différer)

Le fichier .terraform.lock.hcl (dependency lock file) enregistre les versions exactes et les hashes de chaque provider installé. Il garantit que toute l’équipe utilise exactement les mêmes binaires de providers.

Si vous le supprimez, terraform init résout de nouveau les contraintes de version et peut installer une version plus récente (si ~> 5.0 autorise 5.80 alors que le lock plaçait 5.72, par exemple).

Bonnes pratiques :

  • Committer .terraform.lock.hcl dans le répertoire Git
  • Utiliser terraform init -upgrade pour mettre à jour volontairement les providers
  • Ne jamais le mettre dans .gitignore

Exercice 27 — Partage de données entre workspaces HCP

Section intitulée « Exercice 27 — Partage de données entre workspaces HCP »

Question : Dans HCP Terraform, vous voulez que le workspace app consomme le vpc_id produit par le workspace network. Quelle méthode est recommandée par HCP Terraform pour éviter d’exposer l’intégralité du state ?

A. terraform_remote_state avec un backend S3 B. Le data source tfe_outputs C. Une variable set partagée D. Un webhook d’API

Voir la réponse

B. Le data source tfe_outputs

data "tfe_outputs" "network" {
organization = "myorg"
workspace = "network"
}
resource "aws_instance" "app" {
subnet_id = data.tfe_outputs.network.values.private_subnet_ids[0]
}

tfe_outputs est le data source recommandé par HCP Terraform pour le partage inter-workspaces. Contrairement à terraform_remote_state, il n’expose que les outputs (pas l’intégralité du state), et il respecte les permissions RBAC du workspace source.

MéthodeAccèsSécuritéUsage
terraform_remote_stateState completFaibleLegacy, backend S3
tfe_outputsOutputs uniquementRBACRecommandé HCP
Variable setValeurs statiquesAdminCredentials partagées

Notez vos résultats par objectif :

ObjectifExercicesRéussisScore
1 — Resource lifecycle1 à 5_ / 5_ %
2 — Dynamic configuration6 à 11_ / 6_ %
3 — Collaborative workflows12 à 14, 26_ / 4_ %
4 — Modules15 à 17_ / 3_ %
5 — Providers18 à 20_ / 3_ %
6 — HCP Terraform (QCM)21 à 25, 27_ / 6_ %
Total27_ / 27_ %
ScoreNiveauAction
90 %+Prêt pour l’examenPlanifiez votre date
75 – 89 %Presque prêtRenforcez les objectifs faibles
60 – 74 %En progressionReprenez les commandes et refaites les exercices
< 60 %InsuffisantRevoyez les guides de préparation avant de réessayer
  • L’examen lab exige de la vitesse — connaître les commandes par coeur fait la différence
  • moved {} et import {} (déclaratifs) sont préférés aux commandes CLI équivalentes
  • Le pattern flatten + for + for_each est omniprésent dans les labs
  • Les preconditions/postconditions et check blocks sont des sujets récents et fréquents
  • Le provider aliasing multi-région (ACM + CloudFront) est un classique
  • terraform test avec les fichiers .tftest.hcl est un sujet clé depuis Terraform 1.6
  • Le fichier .terraform.lock.hcl doit être committé — il garantit des versions de providers identiques pour toute l’équipe
  • En HCP Terraform, tfe_outputs est préféré à terraform_remote_state pour le partage inter-workspaces
  • L’objectif 6 teste vos connaissances théoriques sur HCP — pas de pratique lab

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn