Comment lire cette page. Chaque section est repliée sous son titre : clique sur « Afficher … » pour l'ouvrir, referme-la quand tu as fini. Ordre de lecture : Objectif, puis En bref (toutes les commandes, à copier dans l'ordre), puis Le code (le fichier
main.tfexpliqué ligne par ligne), puis Terraform, dans le terminal (T1 à T13, une commande à la fois avec sa vraie sortie). Le pas à pas détaillé, avec l'installation des outils, la préparation du compte AWS et la sortie attendue de chaque geste, est en annexe : annexe A pour Windows (PowerShell), annexe B pour Linux, macOS, WSL 2 et Git Bash. Ouvre une seule annexe, celle de ton système. L'annexe C, commune, regroupe les cas où ça coince.
Tu arrives dans une équipe qui gère toute son infrastructure avec Terraform. Avant de te laisser toucher au compte AWS, ta cheffe te demande une chose : « Montre-moi que tu maîtrises le cycle complet sur ta machine. Un fichier, c'est suffisant. Je veux voir le plan avant l'apply, le state après, la modification détectée, et un dossier propre à la fin. » C'est exactement ce projet. Le provider local écrit un fichier texte sur ton disque au lieu de créer un serveur, mais les commandes, les phrases affichées et les fichiers produits sont les mêmes que pour un bucket S3 ou un dépôt GitHub. Tout ce que tu lis ici, tu le reliras dans les huit projets suivants.
Les dix étapes de ce schéma sont détaillées, avec la sortie attendue de chaque commande, dans l'annexe A (Windows) ou l'annexe B (Linux, macOS, WSL 2, Git Bash) en bas de page. Les commandes Terraform elles-mêmes, identiques sur tous les systèmes, sont expliquées une par une dans Terraform, dans le terminal.
Kit du cours : https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr
Tu clones le kit dans un dossier lab-terraform, tu vérifies tes outils, tu crées un dossier de travail vide, tu y écris main.tf toi-même, puis tu déroules le cycle : init, fmt, validate, plan, apply, vérification, state, modification, destroy. À la fin, terraform state list n'affiche plus rien et etat dit Ressources encore gérées : 0 (0 attendu à la fin d'une séance). Le kit contient le corrigé dans projets/01-terraform-local/, à ouvrir seulement si tu bloques : le but est d'écrire le fichier à la main.
Windows (PowerShell)
git clone https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr.git lab-terraform
cd lab-terraform
dir # explorer : labo.ps1, labo.sh, README.md, projets\
.\labo.ps1 prerequis # attendu : Prérequis : 4 outils requis présents sur 4.
.\labo.ps1 nouveau projet-01-local # crée travail\projet-01-local
cd travail\projet-01-local
code . # VS Code : créer main.tf, coller le code de la section « Le code »
terraform init # attendu : Terraform has been successfully initialized!
terraform fmt
terraform validate # attendu : Success! The configuration is valid.
terraform plan # attendu : Plan: 1 to add, 0 to change, 0 to destroy.
terraform apply # répondre yes ; attendu : Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Get-Content .\message.txt # attendu : Bonjour, ce fichier a été créé avec Terraform.
Get-ChildItem -Force # .terraform, .terraform.lock.hcl, main.tf, message.txt, terraform.tfstate
terraform state list # attendu : local_file.message
terraform state show local_file.message
# modifier la ligne content dans main.tf (voir T10), puis :
terraform plan # attendu : Plan: 1 to add, 0 to change, 1 to destroy.
terraform apply # répondre yes ; attendu : Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
Get-Content .\message.txt # attendu : Deuxième version du fichier créée avec Terraform.
terraform destroy # répondre yes ; attendu : Destroy complete! Resources: 1 destroyed.
terraform state list # attendu : rien
cd ..\..
.\labo.ps1 etat # attendu : Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Si PowerShell refuse .\labo.ps1 (« l'exécution de scripts est désactivée sur ce système ») : Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, réponds O, relance.
Linux, macOS, WSL 2, Git Bash
git clone https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr.git lab-terraform
cd lab-terraform
ls # explorer : labo.ps1, labo.sh, README.md, projets/
./labo.sh prerequis # attendu : Prérequis : 4 outils requis présents sur 4.
./labo.sh nouveau projet-01-local # crée travail/projet-01-local
cd travail/projet-01-local
code . # VS Code : créer main.tf, coller le code de la section « Le code »
terraform init # attendu : Terraform has been successfully initialized!
terraform fmt
terraform validate # attendu : Success! The configuration is valid.
terraform plan # attendu : Plan: 1 to add, 0 to change, 0 to destroy.
terraform apply # répondre yes ; attendu : Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
cat message.txt # attendu : Bonjour, ce fichier a été créé avec Terraform.
ls -la # .terraform, .terraform.lock.hcl, main.tf, message.txt, terraform.tfstate
terraform state list # attendu : local_file.message
terraform state show local_file.message
# modifier la ligne content dans main.tf (voir T10), puis :
terraform plan # attendu : Plan: 1 to add, 0 to change, 1 to destroy.
terraform apply # répondre yes ; attendu : Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
cat message.txt # attendu : Deuxième version du fichier créée avec Terraform.
terraform destroy # répondre yes ; attendu : Destroy complete! Resources: 1 destroyed.
terraform state list # attendu : rien
cd ../..
./labo.sh etat # attendu : Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Si ./labo.sh répond Permission denied : chmod +x labo.sh, une seule fois.
Le projet tient dans un seul fichier, main.tf, à créer dans travail/projet-01-local/. Tape-le ou colle-le exactement ainsi (c'est mot pour mot le corrigé du kit, projets/01-terraform-local/main.tf) :
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
provider "local" {}
resource "local_file" "message" {
filename = "${path.module}/message.txt"
content = "Bonjour, ce fichier a été créé avec Terraform."
}Trois blocs, du plus général au plus concret.
| Ligne | Ce qu'elle dit à Terraform |
|---|---|
terraform { … } | Les réglages de Terraform lui-même pour ce dossier. |
required_providers { local = { … } } | « Ce projet a besoin d'un plugin appelé local. » |
source = "hashicorp/local" | Où le télécharger : le provider local publié par HashiCorp sur le Terraform Registry. |
version = "~> 2.5" | Quelle version accepter : 2.5 ou plus récente, mais pas 3.0. Sur la machine du cours, init a choisi v2.9.1. |
provider "local" {} | « Active ce provider. » Les accolades sont vides parce que le provider local n'a rien à configurer (pas de région, pas de compte). |
resource "local_file" "message" { … } | « Gère un objet de type local_file, que j'appelle message dans mon code. » Le type vient du provider (local_ + file) ; le nom est à toi. Ensemble ils forment l'adresse local_file.message. |
filename = "${path.module}/message.txt" | Où écrire le fichier. path.module est le dossier qui contient ce main.tf ; Terraform l'affichera ./message.txt. |
content = "Bonjour, ce fichier a été créé avec Terraform." | Le texte à écrire dedans. C'est cette ligne que tu changeras à l'étape T10. |
Terraform lance les commandes depuis le dossier courant. Si tu écris filename = "message.txt", le fichier est créé là où tu tapes terraform apply, ce qui est en général le bon dossier, mais pas toujours (quand le code est appelé comme module depuis un autre dossier, au module 5). path.module désigne toujours le dossier du fichier .tf, quel que soit l'endroit d'où Terraform est lancé. La syntaxe ${…} insère la valeur d'une expression dans une chaîne de caractères : "${path.module}/message.txt" devient "./message.txt".
Ça marche quand même : Terraform déduit du type local_file qu'il lui faut le provider hashicorp/local, et init affiche Finding latest version of hashicorp/local... au lieu de Finding hashicorp/local versions matching "~> 2.5".... C'est ce que font les deux ateliers fondamentaux de ce module, pour aller au plus court. Mais sans contrainte de version, deux collègues qui lancent init à six mois d'écart peuvent obtenir deux versions différentes du provider. Dans un vrai projet, on écrit toujours le bloc.
Les commandes de cette section se tapent dans le dossier travail/projet-01-local, une fois main.tf écrit. Elles sont identiques sous Windows, Linux et macOS : Terraform est le même programme partout. Les sorties sont celles de la machine du cours (Terraform 1.12.2, Windows 11), capturées telles quelles ; seuls les identifiants (id=ff6b93dc…) et les empreintes changent d'une machine à l'autre. Les commandes qui, elles, dépendent du système (lire le fichier, lister le dossier) sont dans ton annexe.
Une image à garder pour toute la section : la leçon 01 t'a présenté l'architecte. Chaque commande ci-dessous est un de ses gestes. init ouvre le chantier, plan écrit le devis, apply le fait exécuter, state relit le relevé, destroy démonte tout.
La règle : une seule nouveauté par commande. On commence par la commande qui ne prend aucun paramètre et ne touche à rien.
terraform versionTerraform v1.12.2
on windows_amd64Ce que la commande demande : « Terraform, quelle version es-tu, et sur quel système ? » Aucun paramètre, aucun fichier lu, rien de modifié. Si cette commande échoue (terraform : Le terme «terraform» n'est pas reconnu… ou command not found), rien d'autre ne marchera : c'est l'installation ou le PATH, voir l'annexe A.1 ou B.1. Sur la machine du cours, Terraform ajoute parfois deux lignes Your version of Terraform is out of date! : c'est une information, pas une erreur.
L'équivalent connu : aws --version, git --version, python --version. Même geste, même but.
terraform initInitializing the backend...
Initializing provider plugins...
- Finding hashicorp/local versions matching "~> 2.5"...
- Installing hashicorp/local v2.9.1...
- Installed hashicorp/local v2.9.1 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
…Ce que la commande demande : « Lis mon main.tf, télécharge les providers qu'il réclame, et prépare ce dossier pour travailler. »
Une seule nouveauté : le dossier devient un projet Terraform. Lis la sortie ligne par ligne :
| Ligne | Ce qui s'est passé |
|---|---|
Initializing the backend... | Le backend est l'endroit où le state sera rangé. Rien n'est précisé dans main.tf, donc ce sera un fichier local, terraform.tfstate. |
Finding hashicorp/local versions matching "~> 2.5"... | Terraform a lu ta contrainte de version et cherche sur le Registry. |
Installing hashicorp/local v2.9.1... | Il a choisi la plus récente qui respecte ~> 2.5, et la télécharge dans .terraform/. |
(signed by HashiCorp) | Le plugin est signé : tu as bien le vrai provider. |
Terraform has created a lock file .terraform.lock.hcl | La version choisie est notée dans un fichier à garder dans Git : le prochain init, chez un collègue, prendra la même. |
Terraform has been successfully initialized! | La phrase à attendre. |
Deux choses sont apparues dans ton dossier : le répertoire caché .terraform/ (le provider téléchargé, environ 18 Mo sur la machine du cours, à ne jamais mettre dans Git) et le fichier .terraform.lock.hcl (22 lignes, à mettre dans Git). Tu les verras dans l'annexe, étape A.6 ou B.6.
L'équivalent connu : npm install ou pip install -r requirements.txt. On lit une liste de dépendances, on télécharge, on verrouille les versions (package-lock.json).
Terraform refuse de continuer et te dit quoi faire. terraform plan sans init répond :
Error: Inconsistent dependency lock file
The following dependency selections recorded in the lock file are
inconsistent with the current configuration:
- provider registry.terraform.io/hashicorp/local: required by this configuration but no version is selected
To make the initial dependency selections that will initialize the dependency
lock file, run:
terraform initet terraform validate sans init :
Error: Missing required provider
This configuration requires provider registry.terraform.io/hashicorp/local,
but that provider isn't available. You may be able to install it
automatically by running:
terraform initDans les deux cas, la dernière ligne est la solution. init se relance sans risque autant de fois que tu veux ; il ne touche jamais à tes ressources.
terraform fmtCe que la commande demande : « Réaligne les espaces et l'indentation de mes fichiers .tf selon le style officiel. »
Une seule nouveauté : la sortie vide. fmt affiche le nom de chaque fichier qu'il a modifié ; si tu as collé le code tel quel, il n'a rien à corriger et n'affiche rien. Ce n'est pas une erreur, c'est la meilleure réponse possible. Si tu avais mal indenté une ligne, il aurait affiché main.tf et réécrit le fichier.
L'équivalent connu : prettier --write, black, gofmt. Le kit vérifie ce point avec terraform fmt -check -recursive, qui ne modifie rien et sort en erreur (code 3) si un fichier n'est pas au format.
terraform validateSuccess! The configuration is valid.Ce que la commande demande : « Relis mes blocs. Les noms d'arguments existent-ils, les accolades sont-elles fermées, les références pointent-elles vers quelque chose ? »
Une seule nouveauté : Terraform consulte le provider pour connaître les arguments valides d'un local_file. C'est pourquoi validate exige init avant. Il ne lit pas le state, ne contacte aucune API, ne crée rien. La phrase à attendre : Success! The configuration is valid.
Ce qu'il attrape : contenu au lieu de content (An argument named "contenu" is not expected here. Did you mean "content"?), une accolade oubliée (Error: Unclosed configuration block), un guillemet non fermé (Error: Unterminated template string), un type inexistant (The provider hashicorp/local does not support resource type "local_fichier".). L'annexe C les reprend un par un.
Ce qu'il n'attrape pas : un chemin qui n'existe pas, un nom de bucket déjà pris, une mauvaise architecture. validate dit « c'est du HCL correct », pas « c'est une bonne idée ».
terraform planTerraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.message will be created
+ resource "local_file" "message" {
+ content = "Bonjour, ce fichier a été créé avec Terraform."
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./message.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.Ce que la commande demande : « Compare ce que mon code décrit avec ce que tu connais déjà, et dis-moi ce que tu ferais, sans le faire. »
Une seule nouveauté : le devis. Rien n'a été créé ; message.txt n'existe toujours pas. Lis-le de haut en bas :
| Ligne | Comment la lire |
|---|---|
+ create | La légende : dans ce plan, il n'y a que des créations. |
# local_file.message will be created | L'adresse de la ressource (type . nom) et son sort. |
+ resource "local_file" "message" { | Le bloc entier est précédé d'un + : tout est nouveau. |
+ content = "Bonjour, …" | Un attribut que tu as écrit : Terraform connaît sa valeur. |
+ content_md5 = (known after apply) | Un attribut que le provider calculera après la création : l'empreinte du contenu. Terraform ne peut pas la deviner avant. |
+ directory_permission = "0777" | Un attribut que tu n'as pas écrit : le provider a une valeur par défaut. |
+ filename = "./message.txt" | Ton ${path.module}/message.txt, résolu. |
Plan: 1 to add, 0 to change, 0 to destroy. | La ligne à lire en premier, toujours. Une création, aucune modification, aucune destruction. |
Note: You didn't use the -out option… | Information : ce devis n'est pas enregistré ; apply en recalculera un. Sans importance ici. |
L'équivalent connu : git diff avant git commit, ou le mode « simulation » (--dry-run, -WhatIf) d'un script. La différence : un script --dry-run te montre ce qu'il va faire ; terraform plan te montre ce qui manque entre le code et le réel, après avoir relu le réel.
Le provider local expose, pour un local_file, tout ce qu'il sait calculer : six empreintes du contenu (md5, sha1, sha256, sha512, et deux versions encodées en base64), les permissions, l'identifiant. Tu n'en as écrit que deux (filename, content) ; les autres sont des attributs que le provider remplit. C'est la même chose pour un bucket S3 : tu écris trois lignes, le plan en affiche trente (ARN, région, identifiant du propriétaire…). Apprends à repérer les tiennes et à survoler les autres, sauf la dernière ligne Plan: qui ne se survole jamais.
terraform applyTerraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.message will be created
+ resource "local_file" "message" {
+ content = "Bonjour, ce fichier a été créé avec Terraform."
…
+ filename = "./message.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
local_file.message: Creating...
local_file.message: Creation complete after 0s [id=ff6b93dc92e7e1d2ba4f9dad3cc16e03ac649b45]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.Ce que la commande demande : « Recalcule le devis, montre-le-moi, et si je réponds yes, fais-le. »
Une seule nouveauté : la question. Terraform s'arrête sur Enter a value: et attend. Tape yes en entier, puis Entrée. y, Y, oui ou une ligne vide donnent Apply cancelled. et rien n'est touché : c'est une protection, pas un bug. Ensuite trois lignes : Creating..., Creation complete after 0s [id=…] (l'identifiant que le plan annonçait (known after apply) est maintenant connu), et la phrase à attendre : Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Les trois nombres sont ceux du plan.
Maintenant, message.txt existe dans ton dossier, et un nouveau fichier est apparu à côté : terraform.tfstate. Va le vérifier avec ton annexe (A.6 ou B.6) avant de continuer : le fichier contient bien Bonjour, ce fichier a été créé avec Terraform.
L'équivalent connu : un script qui écrit le fichier, Set-Content ou echo > message.txt. La différence : le script écrit et oublie ; Terraform écrit et note dans son relevé qu'il a écrit, sous quel identifiant, avec quel contenu.
terraform state listlocal_file.messageCe que la commande demande : « Liste tout ce que tu gères dans ce dossier. »
Une seule nouveauté : le state se lit. Une ligne, une ressource : l'adresse local_file.message, la même que dans le plan. Cette ligne prouve que Terraform a relié le bloc de ton code au fichier réel : c'est ce qui lui permettra de le modifier ou de le détruire plus tard sans que tu aies à lui redire lequel.
Avant apply, la même commande répondait No state file was found! : le relevé n'existait pas encore. Après destroy (T12), elle ne répondra plus rien du tout.
L'équivalent connu : docker ps, kubectl get pods, aws s3 ls. « Qu'est-ce qui tourne, qu'est-ce qui existe ? » Sauf que state list ne va pas voir le réel : il lit son carnet.
terraform state show local_file.message# local_file.message:
resource "local_file" "message" {
content = "Bonjour, ce fichier a été créé avec Terraform."
content_base64sha256 = "G+tDdGue1Lx5hU3LpqBWf3y3haa0ggckj6t/9bj5ocs="
content_base64sha512 = "oB7gPsGHBDNnXe9Hzx4zQ3/nAF1kM9wlfDV/OdMjPybCPurPeN4P8myOoZxFg3dwvs+xLBRJxo4Q3H0qGS8l5g=="
content_md5 = "6daf774f0eb6d3da439c871afec7cf90"
content_sha1 = "ff6b93dc92e7e1d2ba4f9dad3cc16e03ac649b45"
content_sha256 = "1beb43746b9ed4bc79854dcba6a0567f7cb785a6b48207248fab7ff5b8f9a1cb"
content_sha512 = "a01ee03ec1870433675def47cf1e33437fe7005d6433dc257c357f39d3233f26c23eeacf78de0ff26c8ea19c45837770becfb12c1449c68e10dc7d2a192f25e6"
directory_permission = "0777"
file_permission = "0777"
filename = "./message.txt"
id = "ff6b93dc92e7e1d2ba4f9dad3cc16e03ac649b45"
}Ce que la commande demande : « Montre-moi tout ce que tu sais de la ressource local_file.message. »
Une seule nouveauté : la commande prend un paramètre, l'adresse lue en T7. Compare avec le plan de T5 : toutes les valeurs (known after apply) sont maintenant remplies. L'id est l'empreinte SHA-1 du contenu, la même valeur que content_sha1 et que l'[id=…] affiché par apply. C'est le relevé de l'architecte, pièce par pièce.
Si tu te trompes d'adresse (local_file.mesage), Terraform répond No instance found for the given address! et te renvoie vers terraform state list.
Le fichier terraform.tfstate est du JSON : un numéro de série ("serial"), la version de Terraform, et une liste "resources" où chaque ressource a exactement les attributs que state show t'affiche. Tu peux l'ouvrir pour le lire. Tu ne le modifies jamais à la main : une virgule déplacée, et Terraform ne reconnaît plus ce qu'il a construit, ou croit gérer quelque chose qui n'existe plus. Pour agir sur le state, il y a des commandes (terraform state rm, terraform state mv, terraform import) que tu verras au module 4.
Deux autres règles, dès aujourd'hui. Le state peut contenir des secrets (ici, le texte du fichier ; ailleurs, un mot de passe de base de données) : il ne se partage pas par message ni ne se commite dans Git. Et il est la mémoire de Terraform : si tu le supprimes, Terraform croit que rien n'existe et propose de tout recréer, alors que les ressources sont toujours là et, dans le cloud, toujours facturées.
terraform outputWarning: No outputs found
The state file either has no outputs defined, or all the defined outputs are
empty. Please define an output in your configuration with the `output`
keyword and run `terraform refresh` for it to become available. If you are
using interpolation, please verify the interpolated value is not empty. You
can use the `terraform console` command to assist.Ce que la commande demande : « Affiche les valeurs que le code a choisi d'exposer avec des blocs output. »
Une seule nouveauté : un avertissement (Warning), pas une erreur. Ton main.tf n'a aucun bloc output, donc Terraform n'a rien à afficher et te le dit. Tu écriras tes premiers outputs au projet 02 ; ici, la commande sert à voir la différence entre « ça a échoué » (Error:) et « il n'y a rien à montrer » (Warning:).
Ouvre main.tf, remplace la ligne content par celle-ci, enregistre :
content = "Deuxième version du fichier créée avec Terraform."Puis :
terraform planlocal_file.message: Refreshing state... [id=ff6b93dc92e7e1d2ba4f9dad3cc16e03ac649b45]
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# local_file.message must be replaced
-/+ resource "local_file" "message" {
~ content = "Bonjour, ce fichier a été créé avec Terraform." -> "Deuxième version du fichier créée avec Terraform." # forces replacement
~ content_base64sha256 = "G+tDdGue1Lx5hU3LpqBWf3y3haa0ggckj6t/9bj5ocs=" -> (known after apply)
~ content_base64sha512 = "oB7gPsGHBDNnXe9Hzx4zQ3/nAF1kM9wlfDV/OdMjPybCPurPeN4P8myOoZxFg3dwvs+xLBRJxo4Q3H0qGS8l5g==" -> (known after apply)
~ content_md5 = "6daf774f0eb6d3da439c871afec7cf90" -> (known after apply)
~ content_sha1 = "ff6b93dc92e7e1d2ba4f9dad3cc16e03ac649b45" -> (known after apply)
~ content_sha256 = "1beb43746b9ed4bc79854dcba6a0567f7cb785a6b48207248fab7ff5b8f9a1cb" -> (known after apply)
~ content_sha512 = "a01ee03ec1870433675def47cf1e33437fe7005d6433dc257c357f39d3233f26c23eeacf78de0ff26c8ea19c45837770becfb12c1449c68e10dc7d2a192f25e6" -> (known after apply)
~ id = "ff6b93dc92e7e1d2ba4f9dad3cc16e03ac649b45" -> (known after apply)
# (3 unchanged attributes hidden)
}
Plan: 1 to add, 0 to change, 1 to destroy.Ce que la commande demande : la même chose qu'en T5. Mais cette fois Terraform a un relevé à comparer.
Une seule nouveauté : le symbole -/+, « détruire puis recréer ». Trois indices te le disent, et il faut savoir les repérer :
| Indice | Où | Ce qu'il dit |
|---|---|---|
must be replaced | le titre # local_file.message must be replaced | Ce n'est pas will be updated in-place. |
# forces replacement | au bout de la ligne ~ content = "…" -> "…" | C'est cet attribut qui oblige à remplacer. Le ~ devant dit que la valeur change ; le commentaire dit que ce changement ne peut pas se faire sur place. |
Plan: 1 to add, 0 to change, 1 to destroy. | la dernière ligne | Une destruction et une création, zéro modification. |
Regarde aussi la première ligne, nouvelle : Refreshing state... [id=…]. Avant de comparer, Terraform est allé relire le fichier réel pour vérifier qu'il correspond encore à son relevé. C'est là qu'il détecterait une dérive (leçon 01), si tu avais modifié message.txt à la main.
La différence essentielle entre
~et-/+. Pour un fichier texte, être remplacé ou modifié sur place revient au même : à la fin, le contenu est le nouveau. Pour une base de données, un disque ou un utilisateur,-/+veut dire perte de l'objet et de son identifiant : les données du disque, le mot de passe de l'utilisateur, l'adresse IP du serveur. C'est le provider qui décide, attribut par attribut, ce qui force un remplacement ; toi, tu le lis dans le plan avant de direyes. Le providerlocalremplace le fichier dès quecontentchange : jamais de~seul pour cet attribut.
terraform apply…
Plan: 1 to add, 0 to change, 1 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
local_file.message: Destroying... [id=ff6b93dc92e7e1d2ba4f9dad3cc16e03ac649b45]
local_file.message: Destruction complete after 0s
local_file.message: Creating...
local_file.message: Creation complete after 0s [id=1df9196ac94445f0943c35b75c8c2e1bdf3e0cd6]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.Ce que la commande demande : la même chose qu'en T6.
Rien de neuf dans la commande ; tout est dans la sortie. Quatre lignes d'action au lieu de deux : Destroying..., Destruction complete, puis Creating..., Creation complete. L'ordre est celui du symbole -/+ : le moins d'abord, le plus ensuite. Et l'identifiant a changé (ff6b93dc… avant, 1df9196a… après) : c'est un autre objet, pas le même modifié. Vérifie le nouveau contenu avec ton annexe (A.8 ou B.8) : Deuxième version du fichier créée avec Terraform.
Bilan de T5 à T11 : tu as vu les deux devis que tu reliras toute ta carrière : + (créer) et -/+ (remplacer). Le troisième, ~ (modifier sur place), n'existe pas pour le content d'un local_file ; tu le rencontreras dans les projets cloud, par exemple quand une étiquette (tag) change sur une ressource AWS.
terraform destroylocal_file.message: Refreshing state... [id=1df9196ac94445f0943c35b75c8c2e1bdf3e0cd6]
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# local_file.message will be destroyed
- resource "local_file" "message" {
- content = "Deuxième version du fichier créée avec Terraform." -> null
- content_base64sha256 = "36Hz+L76pjLbvY4LIzPfw+UsqNneFneSfFGjtfRLxkI=" -> null
…
- filename = "./message.txt" -> null
- id = "1df9196ac94445f0943c35b75c8c2e1bdf3e0cd6" -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
local_file.message: Destroying... [id=1df9196ac94445f0943c35b75c8c2e1bdf3e0cd6]
local_file.message: Destruction complete after 0s
Destroy complete! Resources: 1 destroyed.Ce que la commande demande : « Détruis tout ce que tu gères dans ce dossier, et montre-moi le devis d'abord. »
Une seule nouveauté : le symbole - seul, et une question plus grave : Do you really want to destroy all resources? … There is no undo. Chaque attribut passe à -> null : il n'y aura plus rien. La phrase à attendre : Destroy complete! Resources: 1 destroyed. Le fichier message.txt a disparu de ton dossier.
C'est la commande qui clôt chaque séance de ce cours. Ici elle efface un fichier texte ; au projet 03 elle supprimera un bucket qui, sinon, resterait facturé.
terraform state listCe que la commande demande : la même qu'en T7.
Rien de neuf, et une sortie vide : Terraform ne gère plus rien dans ce dossier. Le fichier terraform.tfstate existe toujours, mais sa liste "resources" est [], et un terraform.tfstate.backup est apparu à côté (la version d'avant le destroy, que Terraform garde par prudence). Ton annexe (A.9 et A.10, ou B.9 et B.10) te fait lister le dossier et lancer etat pour la preuve finale : Ressources encore gérées : 0 (0 attendu à la fin d'une séance).
Bilan de T1 à T13 : init une fois, puis fmt, validate, plan, apply, state list, state show, un plan et un apply de modification, destroy, state list. Treize commandes, cinq phrases à reconnaître : successfully initialized!, The configuration is valid., Plan: N to add, N to change, N to destroy., Apply complete!, Destroy complete!.
Le message à faire passer. Un script PowerShell ou bash aurait écrit
message.txten une ligne, et l'aurait supprimé en une autre. Ce que le script ne fait pas et que tu as vu Terraform faire : annoncer avant d'agir (plan), demander un accord explicite (yes), noter ce qu'il a créé (state list), relire le réel avant chaque décision (Refreshing state...), distinguer modifier de remplacer (-/+), et savoir tout défaire sans qu'on lui redise quoi (destroy).
Le projet 01 ne touche pas à AWS. Mais le projet 03 crée un vrai bucket S3, et tu auras besoin d'un compte prêt. Cette section se fait dans le navigateur, elle est identique sous Windows, Linux et macOS, et tu peux la faire avant ou après le cycle Terraform de ce projet. Les commandes aws configure et aws sts get-caller-identity qui l'accompagnent sont dans ton annexe (A.2 ou B.2).
Si tu travailles dans AWS Academy, AWS Educate, un sandbox fourni par l'école ou un compte temporaire de laboratoire : utilise les identifiants fournis par la plateforme et passe directement à l'étape A.2 ou B.2 (cas « Academy »). Ne crée pas d'utilisateur IAM si ton enseignant te donne déjà des accès temporaires.
ca-central-1 si le laboratoire n'en impose pas une autre.Le compte root sert uniquement à créer le compte, gérer la facturation et faire les opérations sensibles. Active la MFA (authentification à deux facteurs) sur le compte root, puis crée un utilisateur séparé pour le travail de laboratoire, ci-dessous.
IAM et ouvre le service IAM.terraform-admins.AdministratorAccess, coche la politique AdministratorAccess.Pour un laboratoire seulement.
AdministratorAccessdonne un accès complet à tous les services et ressources du compte. C'est pratique pour apprendre ; ce n'est pas un modèle de sécurité pour la production, où l'on donne à Terraform les seules permissions dont il a besoin (module 4).
terraform-admin.terraform-admins → Next → Create user.terraform-admin.aws-cli-terraform-lab → Create access key..csv ou copie Access key et Secret access key dans un gestionnaire de mots de passe. La Secret access key ne sera plus jamais affichée.À ne jamais faire. Ne colle jamais une Access Key, une Secret Access Key, un token de session, un fichier
.envou unterraform.tfstatedans GitHub, Word, Teams, Discord, Slack, un ticket ou un courriel. Ces éléments donnent accès au compte. Si une clé fuit : IAM → l'utilisateur → Security credentials → Deactivate puis Delete, et on en crée une autre.
Avant de relancer terraform destroy une deuxième fois sur un dossier déjà détruit, écris sur papier ce que la dernière ligne du plan va dire. Puis lance-le. Ensuite, recrée le fichier avec terraform apply, ouvre message.txt dans VS Code, ajoute un mot à la main, enregistre, et tape terraform plan : que dit la ligne Refreshing state..., quel symbole apparaît, et comment appelle-t-on cet écart dans la leçon 01 ? Termine par destroy : le dossier doit revenir à Ressources encore gérées : 0.
Toutes les commandes de cette annexe se tapent dans PowerShell (Windows Terminal ou PowerShell 7), avec .\labo.ps1 …. Les sorties reproduites sont celles de la machine du cours, sous Windows 11 et Terraform 1.12.2.
git --version répond), VS Code installé avec la commande code disponible dans PowerShell (sinon : VS Code → Ctrl+Shift+P → « Shell Command: Install 'code' command in PATH », ou réinstalle en cochant « Add to PATH »)..\labo.ps1 (« l'exécution de scripts est désactivée sur ce système ») : Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, réponds O, relance. Une seule fois par machine..\labo.ps1 etat doit afficher Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Le plus simple, avec le gestionnaire de paquets de Windows :
winget install Hashicorp.TerraformFerme PowerShell, rouvre-le, puis :
terraform versionPoint de contrôle :
Terraform v1.12.2
on windows_amd64Ta version peut être plus récente ; tout ce qui est 1.6 ou plus convient. Si Terraform ajoute Your version of Terraform is out of date!, c'est une information, pas une erreur.
Sans winget, avec le binaire officiel : va sur https://developer.hashicorp.com/terraform/install, choisis Windows, télécharge la version AMD64, décompresse le .zip, crée le dossier C:\terraform, déplace terraform.exe dedans, puis ajoute C:\terraform au PATH : menu Démarrer → « variables d'environnement » → Modifier les variables d'environnement système → Variables d'environnement → dans Variables système, sélectionne Path → Modifier → Nouveau → C:\terraform → OK. Ferme toutes les fenêtres PowerShell, rouvre, retape terraform version.
Si tu vois autre chose : terraform : Le terme «terraform» n'est pas reconnu comme nom d'applet de commande… → Terraform n'est pas dans le PATH, ou PowerShell n'a pas été redémarré après l'installation. Annexe C.
Le projet 01 n'utilise pas AWS ; cette étape prépare le projet 03. Tu peux la faire maintenant ou la remettre à plus tard.
.msi : Next, accepte la licence, garde le dossier par défaut, Install.aws --versionPoint de contrôle : une version qui commence par aws-cli/2 (sur la machine du cours : aws-cli/2.22.18). Si tu vois aws-cli/1, c'est l'ancienne version : désinstalle-la.
Puis configure les clés créées dans la section La console AWS, dans le navigateur :
aws configureAWS Access Key ID [None]: TON_ACCESS_KEY_ID
AWS Secret Access Key [None]: TA_SECRET_ACCESS_KEY
Default region name [None]: ca-central-1
Default output format [None]: jsonVérifie que la CLI parle bien à AWS :
aws sts get-caller-identityExemple de réponse (les valeurs sont celles de ton compte) :
{
"UserId": "AIDA...",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/terraform-admin"
}Cas AWS Academy ou sandbox temporaire : ouvre le laboratoire, clique sur AWS Details ou Credentials, copie Access Key, Secret Key et Session Token (obligatoire avec des accès temporaires), puis :
aws configure set aws_access_key_id TON_ACCESS_KEY_ID
aws configure set aws_secret_access_key TA_SECRET_ACCESS_KEY
aws configure set aws_session_token TON_SESSION_TOKEN
aws configure set region ca-central-1
aws configure set output json
aws sts get-caller-identityPlace-toi dans le dossier où tu ranges tes projets (par exemple C:\Users\<toi>\Documents), puis :
git clone https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr.git lab-terraform
cd lab-terraform
dirPoint de contrôle : dir liste projets, labo.ps1, labo.sh, README.md (et .gitattributes, .gitignore avec dir -Force). Puis :
.\labo.ps1 prerequisOK terraform 1.12.2
OK aws 2.22.18
OK git 2.49.0.windows.1
OK code 1.135.0
OK gh 2.81.0 (optionnel)
ABSENT az (optionnel, projet 08B seulement)
OK gcloud 544.0.0 (optionnel)
Prérequis : 4 outils requis présents sur 4.Les quatre outils requis sont terraform, aws, git et code. gh, az et gcloud sont optionnels et peuvent être ABSENT sans conséquence avant le module 3. Si aws est ABSENT parce que tu as remis A.2 à plus tard, la dernière ligne dit 3 outils requis présents sur 4 : tu peux quand même continuer ce projet.
.\labo.ps1 nouveau projet-01-localDossier travail\projet-01-local créé (ignoré par Git). Tapez :
cd travail\projet-01-localFais ce que le script te dit, puis ouvre le dossier dans VS Code :
cd travail\projet-01-local
code .Le dossier travail\ est ignoré par Git : tu peux y écrire librement sans salir le kit. Le corrigé reste dans projets\01-terraform-local\.
Si code . ne fait rien : ouvre VS Code à la main, File → Open Folder, et choisis lab-terraform\travail\projet-01-local.
main.tfDans VS Code : icône New File dans l'explorateur de gauche, nomme le fichier main.tf (attention : pas main.tf.txt, VS Code n'ajoute pas d'extension mais le Bloc-notes Windows le ferait), colle le code de la section Le code : fichier par fichier, enregistre avec Ctrl+S.
Vérifie depuis PowerShell :
Get-Content .\main.tfPoint de contrôle : les quinze lignes du fichier, de terraform { à }. Puis :
Get-ChildItemUne seule entrée : main.tf. Si tu vois main.tf.txt, renomme : Rename-Item main.tf.txt main.tf.
Déroule T2 à T6 de la section Terraform, dans le terminal :
terraform init
terraform fmt
terraform validate
terraform plan
terraform applyRéponds yes à la question de apply. Points de contrôle, dans l'ordre : Terraform has been successfully initialized!, rien pour fmt, Success! The configuration is valid., Plan: 1 to add, 0 to change, 0 to destroy., Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Vérifie ce qui est apparu dans le dossier :
Get-ChildItem -Force.terraform
.terraform.lock.hcl
main.tf
message.txt
terraform.tfstate(-Force affiche aussi les entrées cachées, celles dont le nom commence par un point ; sans lui, tu ne verrais que main.tf, message.txt et terraform.tfstate.) Cinq entrées :
| Entrée | Qui l'a créée | Ce que c'est |
|---|---|---|
.terraform | init | Dossier caché, le provider téléchargé. Jamais dans Git. |
.terraform.lock.hcl | init | Les versions de providers choisies. Dans Git. |
main.tf | toi | Le code. |
message.txt | apply | La ressource. |
terraform.tfstate | apply | Le state, le relevé. Jamais dans Git, jamais partagé. |
Lis le fichier créé :
Get-Content .\message.txtBonjour, ce fichier a été créé avec Terraform.Tu peux aussi le vérifier dans l'explorateur Windows : ouvre le dossier lab-terraform\travail\projet-01-local, double-clique sur message.txt.
Déroule T7, T8 et T9 :
terraform state list
terraform state show local_file.message
terraform outputPoints de contrôle : local_file.message ; le bloc complet avec filename = "./message.txt" et un id de quarante caractères ; Warning: No outputs found.
Si tu es curieux, regarde le state lui-même, sans le modifier :
Get-Content .\terraform.tfstateDu JSON avec "serial", "terraform_version": "1.12.2" et une liste "resources" contenant local_file.message. Referme-le. On ne l'édite jamais à la main.
Dans VS Code, remplace la ligne content de main.tf par :
content = "Deuxième version du fichier créée avec Terraform."Enregistre, puis déroule T10 et T11 :
terraform plan
terraform applyRéponds yes. Points de contrôle : # local_file.message must be replaced, # forces replacement au bout de la ligne content, Plan: 1 to add, 0 to change, 1 to destroy., puis Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
Get-Content .\message.txtDeuxième version du fichier créée avec Terraform.Déroule T12 et T13 :
terraform destroy
terraform state listRéponds yes. Points de contrôle : Destroy complete! Resources: 1 destroyed., puis une sortie vide pour state list.
Get-ChildItem -Force.terraform
.terraform.lock.hcl
main.tf
terraform.tfstate
terraform.tfstate.backupmessage.txt a disparu. terraform.tfstate est toujours là mais ne contient plus de ressource ; terraform.tfstate.backup est la copie d'avant le destroy. .terraform et .terraform.lock.hcl restent : c'est normal, ils te serviront si tu relances apply.
Remonte à la racine du kit et lance etat :
cd ..\..
.\labo.ps1 etattravail projet-01-local : aucune ressource
Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Si tu avais oublié le destroy, la sortie dirait travail projet-01-local : 1 ressource dans le state puis Ressources encore gérées : 1 (0 attendu à la fin d'une séance). : c'est le garde-fou que tu lanceras à la fin de chaque séance, quand les ressources seront facturées.
Pour recommencer à zéro, plutôt que de nettoyer le dossier : .\labo.ps1 nouveau projet-01-reprise, et tu repars d'un dossier vide.
Toutes les commandes de cette annexe se tapent dans un terminal bash (ou zsh sur macOS), avec ./labo.sh …. Les sorties Terraform sont celles de la machine du cours (Terraform 1.12.2) ; les sorties ls -la ont été capturées sous Git Bash, les colonnes de droits, de propriétaire et de date diffèrent chez toi.
git --version répond), VS Code installé avec la commande code disponible dans le terminal (sur macOS : VS Code → Cmd+Shift+P → « Shell Command: Install 'code' command in PATH »)../labo.sh répond Permission denied : chmod +x labo.sh, une seule fois../labo.sh etat doit afficher Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Suis la page officielle https://developer.hashicorp.com/terraform/install pour ton système. En résumé :
apt avec la clé GPG, commandes copiées depuis la page officielle), puis sudo apt-get install terraform.brew tap hashicorp/tap puis brew install hashicorp/tap/terraform..zip Linux AMD64 (ou ARM64), unzip, puis sudo mv terraform /usr/local/bin/.winget), Git Bash le voit dans le PATH.Ferme le terminal, rouvre-le, puis :
terraform versionPoint de contrôle : Terraform v1.12.2 (ou plus récent) suivi de on linux_amd64, on darwin_arm64 ou on windows_amd64 selon ta machine. Tout ce qui est 1.6 ou plus convient.
Si tu vois autre chose : bash: terraform: command not found → le binaire n'est pas dans un dossier du PATH (echo $PATH), ou le terminal n'a pas été rouvert. Annexe C.
Le projet 01 n'utilise pas AWS ; cette étape prépare le projet 03. Tu peux la faire maintenant ou la remettre à plus tard.
Suis https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html pour ton système (paquet .zip avec ./aws/install sous Linux, .pkg sous macOS). Puis :
aws --versionPoint de contrôle : une version qui commence par aws-cli/2. Si tu vois aws-cli/1, c'est l'ancienne version : désinstalle-la.
Configure les clés créées dans la section La console AWS, dans le navigateur :
aws configureAWS Access Key ID [None]: TON_ACCESS_KEY_ID
AWS Secret Access Key [None]: TA_SECRET_ACCESS_KEY
Default region name [None]: ca-central-1
Default output format [None]: jsonVérifie que la CLI parle bien à AWS :
aws sts get-caller-identityExemple de réponse (les valeurs sont celles de ton compte) :
{
"UserId": "AIDA...",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/terraform-admin"
}Cas AWS Academy ou sandbox temporaire : ouvre le laboratoire, clique sur AWS Details ou Credentials, copie Access Key, Secret Key et Session Token (obligatoire avec des accès temporaires), puis :
aws configure set aws_access_key_id TON_ACCESS_KEY_ID
aws configure set aws_secret_access_key TA_SECRET_ACCESS_KEY
aws configure set aws_session_token TON_SESSION_TOKEN
aws configure set region ca-central-1
aws configure set output json
aws sts get-caller-identityPlace-toi dans le dossier où tu ranges tes projets (par exemple ~/projets), puis :
git clone https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr.git lab-terraform
cd lab-terraform
lsPoint de contrôle : ls liste labo.ps1 labo.sh projets README.md (et .gitattributes, .gitignore avec ls -a). Puis :
./labo.sh prerequisOK terraform 1.12.2
OK aws 2.22.18
OK git 2.49.0.windows.1
OK code 1.135.0
OK gh 2.81.0 (optionnel)
ABSENT az (optionnel, projet 08B seulement)
OK gcloud 544.0.0 (optionnel)
Prérequis : 4 outils requis présents sur 4.(Sortie capturée sous Git Bash, d'où le git 2.49.0.windows.1 ; sous Linux tu liras ta version de Git.) Les quatre outils requis sont terraform, aws, git et code. gh, az et gcloud sont optionnels et peuvent être ABSENT sans conséquence avant le module 3. Si aws est ABSENT parce que tu as remis B.2 à plus tard, la dernière ligne dit 3 outils requis présents sur 4 : tu peux quand même continuer ce projet.
./labo.sh nouveau projet-01-localDossier travail/projet-01-local créé (ignoré par Git). Tapez :
cd travail/projet-01-localFais ce que le script te dit, puis ouvre le dossier dans VS Code :
cd travail/projet-01-local
code .Le dossier travail/ est ignoré par Git : tu peux y écrire librement sans salir le kit. Le corrigé reste dans projets/01-terraform-local/.
Si code . ne fait rien : ouvre VS Code à la main, File → Open Folder, et choisis lab-terraform/travail/projet-01-local.
main.tfDans VS Code : icône New File dans l'explorateur de gauche, nomme le fichier main.tf, colle le code de la section Le code : fichier par fichier, enregistre avec Ctrl+S (Cmd+S sur macOS).
Troisième chemin, sans éditeur, si tu préfères le terminal :
cat > main.tf <<'EOF'
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
provider "local" {}
resource "local_file" "message" {
filename = "${path.module}/message.txt"
content = "Bonjour, ce fichier a été créé avec Terraform."
}
EOF(Les apostrophes autour de 'EOF' empêchent bash d'interpréter ${path.module} : sans elles, la ligne filename serait vidée.) Vérifie :
cat main.tf
ls -latotal 1
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 .
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 ..
-rw-r--r-- 1 rehou 197609 286 sept. 15 14:47 main.tfPoint de contrôle : les quinze lignes du fichier, et une seule entrée dans le dossier, main.tf, d'environ 286 octets.
Déroule T2 à T6 de la section Terraform, dans le terminal :
terraform init
terraform fmt
terraform validate
terraform plan
terraform applyRéponds yes à la question de apply. Points de contrôle, dans l'ordre : Terraform has been successfully initialized!, rien pour fmt, Success! The configuration is valid., Plan: 1 to add, 0 to change, 0 to destroy., Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Vérifie ce qui est apparu dans le dossier :
ls -latotal 14
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 .
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 ..
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 .terraform
-rw-r--r-- 1 rehou 197609 1257 sept. 15 14:47 .terraform.lock.hcl
-rw-r--r-- 1 rehou 197609 286 sept. 15 14:47 main.tf
-rw-r--r-- 1 rehou 197609 50 sept. 15 14:47 message.txt
-rw-r--r-- 1 rehou 197609 1667 sept. 15 14:47 terraform.tfstate(-a affiche aussi les entrées cachées, celles dont le nom commence par un point ; -l donne le détail.) Cinq entrées en plus de . et .. :
| Entrée | Qui l'a créée | Ce que c'est |
|---|---|---|
.terraform | init | Dossier caché, le provider téléchargé. Jamais dans Git. |
.terraform.lock.hcl | init | Les versions de providers choisies. Dans Git. |
main.tf | toi | Le code. |
message.txt | apply | La ressource. 50 octets : le texte, sans retour à la ligne final. |
terraform.tfstate | apply | Le state, le relevé. Jamais dans Git, jamais partagé. |
Lis le fichier créé :
cat message.txtBonjour, ce fichier a été créé avec Terraform.(Le fichier n'a pas de retour à la ligne final : ton invite de commande peut apparaître collée à la fin de la phrase. C'est normal.)
Déroule T7, T8 et T9 :
terraform state list
terraform state show local_file.message
terraform outputPoints de contrôle : local_file.message ; le bloc complet avec filename = "./message.txt" et un id de quarante caractères ; Warning: No outputs found.
Si tu es curieux, regarde le state lui-même, sans le modifier :
cat terraform.tfstateDu JSON avec "serial", "terraform_version": "1.12.2" et une liste "resources" contenant local_file.message. Referme-le. On ne l'édite jamais à la main.
Dans VS Code, remplace la ligne content de main.tf par :
content = "Deuxième version du fichier créée avec Terraform."Enregistre, puis déroule T10 et T11 :
terraform plan
terraform applyRéponds yes. Points de contrôle : # local_file.message must be replaced, # forces replacement au bout de la ligne content, Plan: 1 to add, 0 to change, 1 to destroy., puis Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
cat message.txtDeuxième version du fichier créée avec Terraform.Déroule T12 et T13 :
terraform destroy
terraform state listRéponds yes. Points de contrôle : Destroy complete! Resources: 1 destroyed., puis une sortie vide pour state list.
ls -latotal 17
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 .
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 ..
drwxr-xr-x 1 rehou 197609 0 sept. 15 14:47 .terraform
-rw-r--r-- 1 rehou 197609 1257 sept. 15 14:47 .terraform.lock.hcl
-rw-r--r-- 1 rehou 197609 286 sept. 15 14:47 main.tf
-rw-r--r-- 1 rehou 197609 181 sept. 15 14:47 terraform.tfstate
-rw-r--r-- 1 rehou 197609 1667 sept. 15 14:47 terraform.tfstate.backupmessage.txt a disparu. terraform.tfstate est passé de 1667 à 181 octets : il ne contient plus de ressource ; terraform.tfstate.backup (1667 octets) est la copie d'avant le destroy. .terraform et .terraform.lock.hcl restent : c'est normal, ils te serviront si tu relances apply.
cat terraform.tfstate{
"version": 4,
"terraform_version": "1.12.2",
"serial": 3,
"lineage": "9ddb3372-803f-0964-7665-8413b8f65ee1",
"outputs": {},
"resources": [],
"check_results": null
}"resources": [] : le relevé est vide. Ton lineage (l'identifiant unique de ce state) sera différent.
Remonte à la racine du kit et lance etat :
cd ../..
./labo.sh etattravail projet-01-local : aucune ressource
Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Si tu avais oublié le destroy, la sortie dirait travail projet-01-local : 1 ressource dans le state puis Ressources encore gérées : 1 (0 attendu à la fin d'une séance). : c'est le garde-fou que tu lanceras à la fin de chaque séance, quand les ressources seront facturées.
Pour recommencer à zéro, plutôt que de nettoyer le dossier : ./labo.sh nouveau projet-01-reprise, et tu repars d'un dossier vide.
Chaque cas : le message exact → la cause → le geste.
terraform plan répond Error: Inconsistent dependency lock file … required by this configuration but no version is selected → Tu n'as pas lancé terraform init dans ce dossier (ou tu as ajouté un provider depuis). Le message finit par la solution : terraform init, puis relance.
terraform validate répond Error: Missing required provider … You may be able to install it automatically by running: terraform init → Même cause, même geste : terraform init.
Error: Unsupported argument … An argument named "contenu" is not expected here. Did you mean "content"? → Faute de frappe dans un nom d'argument. Terraform propose souvent le bon mot. Corrige, réenregistre, relance validate.
Error: Unclosed configuration block … There is no closing brace for this block before the end of the file. → Une accolade } manque. Compte-les : chaque { a son }. Dans main.tf, il y en a trois paires imbriquées pour le bloc terraform, une pour provider, une pour resource.
Error: Invalid multi-line string puis Error: Unterminated template string … No closing marker was found for the string. → Un guillemet " manque à la fin d'une valeur. La ligne fautive est citée (3: content = "Bonjour Terraform).
Error: Invalid resource type … The provider hashicorp/local does not support resource type "local_fichier". → Le type de ressource n'existe pas dans ce provider. Les types du provider local s'appellent local_file et local_sensitive_file ; la documentation du provider sur le Registry en donne la liste.
Error: Invalid Attribute Combination … No attribute specified when one (and only one) of [content,sensitive_content,content_base64] is required (répété quatre fois) → Tu as retiré la ligne content : un local_file doit dire ce qu'il contient. Remets-la.
terraform validate dit Success! mais terraform plan répond Error: No configuration files … create a Terraform configuration file (.tf file) and try again. → Il n'y a aucun fichier .tf dans le dossier : soit tu n'es pas dans travail/projet-01-local (vérifie avec pwd), soit le fichier s'appelle main.tf.txt. Renomme-le en main.tf. Un dossier vide est une configuration valide (vide), d'où le Success! trompeur.
terraform apply répond Apply cancelled. et rien n'est créé → Tu as tapé autre chose que yes (par exemple y, Y, oui, ou Entrée seul). Relance et tape yes en entier.
terraform state list répond No state file was found! → Aucun apply n'a encore été fait dans ce dossier, ou tu n'es pas dans le bon dossier. Ce n'est pas une panne : il n'y a encore rien à lister.
terraform state show répond No instance found for the given address! → L'adresse est mal tapée, ou la ressource a été détruite. terraform state list donne les adresses exactes.
terraform fmt -check sort en erreur (code 3) en affichant main.tf → Le fichier n'est pas au format officiel (indentation, alignement des =). Ce n'est pas une erreur de syntaxe : terraform fmt sans -check le corrige.
Après destroy, terraform.tfstate est toujours là et tu crois que le destroy a échoué → Non : ouvre-le, "resources": []. Le fichier reste, vide, avec un terraform.tfstate.backup à côté. Destroy complete! Resources: 1 destroyed. fait foi.
.\labo.ps1 etat ou ./labo.sh etat affiche Ressources encore gérées : 1 → Un destroy a été oublié dans un des dossiers listés au-dessus (travail projet-01-local : 1 ressource dans le state). Va dans ce dossier, terraform destroy, yes, relance etat.
Windows seulement — terraform : Le terme «terraform» n'est pas reconnu comme nom d'applet de commande, fonction, fichier de script ou programme exécutable. → Terraform n'est pas dans le PATH, ou PowerShell n'a pas été redémarré après l'installation. Ferme toutes les fenêtres PowerShell, rouvre, retape terraform version. Si ça persiste, annexe A.1 (ajout de C:\terraform au PATH).
Windows seulement — aws : Le terme «aws» n'est pas reconnu… → AWS CLI n'est pas installé ou PowerShell n'a pas été redémarré. Réinstalle AWS CLI version 2 (A.2), ferme et rouvre PowerShell, retape aws --version.
Windows seulement — .\labo.ps1 est refusé : « l'exécution de scripts est désactivée sur ce système » → Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, réponds O, relance. Une seule fois par machine.
Windows seulement — le fichier s'appelle main.tf.txt → Le Bloc-notes ajoute .txt. Dans PowerShell : Rename-Item main.tf.txt main.tf. Utilise VS Code pour créer les fichiers.
Linux natif et macOS — bash: terraform: command not found → Le binaire n'est pas dans un dossier du PATH. sudo mv terraform /usr/local/bin/, ou vérifie l'installation par paquet (B.1). Rouvre le terminal.
macOS et bash — ./labo.sh répond Permission denied → chmod +x labo.sh, une seule fois. Si bash: ./labo.sh: /bin/bash^M: bad interpreter, le fichier a des fins de ligne Windows : git config core.autocrlf input puis re-clone, ou sed -i 's/\r$//' labo.sh (sed -i '' … sur macOS).
aws sts get-caller-identity répond AccessDenied ou InvalidClientTokenId → La clé configurée n'est pas la bonne, ou le token de session Academy a expiré. aws configure avec la clé de terraform-admin (vérifie que l'utilisateur est dans terraform-admins avec AdministratorAccess), ou refais aws configure set … avec de nouveaux identifiants Academy. Sans effet sur le projet 01, qui n'appelle pas AWS.
Un dossier compressé ou un dépôt Git contenant :
main.tf (le fichier final, avec la deuxième version du content) ;sorties.txt : la sortie complète de terraform plan (première version), de terraform state list après apply, du terraform plan de modification (celui avec must be replaced), et de terraform state list après destroy (vide) ;README.md sur le modèle ci-dessous.Ne remets ni le dossier .terraform/, ni terraform.tfstate, ni aucune Access Key.
# Projet 01 — Terraform local
- Terraform : (sortie de `terraform version`)
- Système : Windows / Linux / macOS
## Ce que j'ai fait
init, fmt, validate, plan, apply, state list, state show, modification de content, plan, apply, destroy, state list.
## Le fichier terraform.tfstate, en trois lignes à moi
(À quoi il sert. Pourquoi Terraform en a besoin pour destroy. Pourquoi on ne l'édite pas et on ne le partage pas.)
## Ce qui m'a bloqué, et comment j'ai débloqué
(Une ligne, ou « rien ».)init, fmt, validate, plan, apply, state, destroy) : https://developer.hashicorp.com/terraform/cli/commandshashicorp/local, ressource local_file : https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/fileAdministratorAccess : https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess.htmlPhrase à retenir : Terraform ne clique pas dans la console à ta place. Il lit ton code, le compare à son state et au réel, t'annonce ce qui va changer, puis crée, remplace ou détruit pour atteindre l'état demandé.