Cómo leer esta página. Cada sección está plegada bajo su título: haz clic en «Mostrar…» para abrirla, ciérrala cuando termines. Orden de lectura: Objetivo, luego En resumen (todos los comandos, para copiar en orden), luego El código (el archivo
main.tfexplicado línea por línea), luego Terraform, en la terminal (T1 a T13, un comando a la vez con su salida real). El paso a paso detallado, con la instalación de las herramientas, la preparación de la cuenta AWS y la salida esperada de cada gesto, está en el anexo: anexo A para Windows (PowerShell), anexo B para Linux, macOS, WSL 2 y Git Bash. Abre un solo anexo, el de tu sistema. El anexo C, común, agrupa los casos en los que algo se traba.
Llegas a un equipo que gestiona toda su infraestructura con Terraform. Antes de dejarte tocar la cuenta AWS, tu jefa te pide una cosa: «Muéstrame que dominas el ciclo completo en tu máquina. Un archivo es suficiente. Quiero ver el plan antes del apply, el state después, la modificación detectada, y una carpeta limpia al final.» Es exactamente este proyecto. El provider local escribe un archivo de texto en tu disco en lugar de crear un servidor, pero los comandos, las frases mostradas y los archivos producidos son los mismos que para un bucket S3 o un repositorio GitHub. Todo lo que lees aquí lo volverás a leer en los ocho proyectos siguientes.
Los diez pasos de este esquema se detallan, con la salida esperada de cada comando, en el anexo A (Windows) o el anexo B (Linux, macOS, WSL 2, Git Bash) al final de la página. Los comandos de Terraform en sí, idénticos en todos los sistemas, se explican uno por uno en Terraform, en la terminal.
Kit del curso: https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr
Clonas el kit en una carpeta lab-terraform, verificas tus herramientas, creas una carpeta de trabajo vacía, escribes tú mismo main.tf en ella, luego recorres el ciclo: init, fmt, validate, plan, apply, verificación, state, modificación, destroy. Al final, terraform state list ya no muestra nada y etat dice Ressources encore gérées : 0 (0 attendu à la fin d'une séance). El kit contiene el corregido en projets/01-terraform-local/, para abrir solo si te quedas atascado: el objetivo es escribir el archivo a mano.
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 rechaza .\labo.ps1 («la ejecución de scripts está deshabilitada en este sistema»): Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, responde O, vuelve a lanzar.
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 responde Permission denied: chmod +x labo.sh, una sola vez.
El proyecto cabe en un solo archivo, main.tf, que debes crear en travail/projet-01-local/. Escríbelo o pégalo exactamente así (es palabra por palabra el corregido del 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."
}Tres bloques, de lo más general a lo más concreto.
| Línea | Qué le dice a Terraform |
|---|---|
terraform { … } | Los ajustes de Terraform mismo para esta carpeta. |
required_providers { local = { … } } | «Este proyecto necesita un plugin llamado local.» |
source = "hashicorp/local" | Dónde descargarlo: el provider local publicado por HashiCorp en el Terraform Registry. |
version = "~> 2.5" | Qué versión aceptar: 2.5 o más reciente, pero no 3.0. En la máquina del curso, init eligió v2.9.1. |
provider "local" {} | «Activa este provider.» Las llaves están vacías porque el provider local no tiene nada que configurar (sin región, sin cuenta). |
resource "local_file" "message" { … } | «Gestiona un objeto de tipo local_file, que llamo message en mi código.» El tipo viene del provider (local_ + file); el nombre es tuyo. Juntos forman la dirección local_file.message. |
filename = "${path.module}/message.txt" | Dónde escribir el archivo. path.module es la carpeta que contiene este main.tf; Terraform lo mostrará como ./message.txt. |
content = "Bonjour, ce fichier a été créé avec Terraform." | El texto que se escribirá dentro. Es esta línea la que cambiarás en el paso T10. |
Terraform lanza los comandos desde la carpeta actual. Si escribes filename = "message.txt", el archivo se crea donde escribes terraform apply, lo que generalmente es la carpeta correcta, pero no siempre (cuando el código se llama como módulo desde otra carpeta, en el módulo 5). path.module designa siempre la carpeta del archivo .tf, sin importar desde dónde se lance Terraform. La sintaxis ${…} inserta el valor de una expresión en una cadena de caracteres: "${path.module}/message.txt" se convierte en "./message.txt".
Funciona igual: Terraform deduce del tipo local_file que necesita el provider hashicorp/local, y init muestra Finding latest version of hashicorp/local... en lugar de Finding hashicorp/local versions matching "~> 2.5".... Es lo que hacen los dos talleres fundamentales de este módulo, para ir más rápido. Pero sin restricción de versión, dos colegas que lancen init con seis meses de diferencia pueden obtener dos versiones distintas del provider. En un proyecto real, siempre se escribe el bloque.
Los comandos de esta sección se escriben en la carpeta travail/projet-01-local, una vez escrito main.tf. Son idénticos en Windows, Linux y macOS: Terraform es el mismo programa en todas partes. Las salidas son las de la máquina del curso (Terraform 1.12.2, Windows 11), capturadas tal cual; solo los identificadores (id=ff6b93dc…) y las huellas cambian de una máquina a otra. Los comandos que sí dependen del sistema (leer el archivo, listar la carpeta) están en tu anexo.
Una imagen para conservar durante toda la sección: la lección 01 te presentó al arquitecto. Cada comando a continuación es uno de sus gestos. init abre la obra, plan escribe el presupuesto, apply lo hace ejecutar, state relee el registro, destroy desmonta todo.
La regla: una sola novedad por comando. Se empieza con el comando que no toma ningún parámetro y no toca nada.
terraform versionTerraform v1.12.2
on windows_amd64Lo que pide el comando: «Terraform, ¿qué versión eres, y en qué sistema?» Ningún parámetro, ningún archivo leído, nada modificado. Si este comando falla (terraform : Le terme «terraform» n'est pas reconnu… o command not found), nada más funcionará: es la instalación o el PATH, ver el anexo A.1 o B.1. En la máquina del curso, Terraform a veces añade dos líneas Your version of Terraform is out of date!: es información, no un error.
El equivalente conocido: aws --version, git --version, python --version. Mismo gesto, mismo propósito.
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.
…Lo que pide el comando: «Lee mi main.tf, descarga los providers que necesita, y prepara esta carpeta para trabajar.»
Una sola novedad: la carpeta se convierte en un proyecto Terraform. Lee la salida línea por línea:
| Línea | Qué ocurrió |
|---|---|
Initializing the backend... | El backend es el lugar donde se guardará el state. Nada se especifica en main.tf, así que será un archivo local, terraform.tfstate. |
Finding hashicorp/local versions matching "~> 2.5"... | Terraform leyó tu restricción de versión y busca en el Registry. |
Installing hashicorp/local v2.9.1... | Eligió la más reciente que respeta ~> 2.5, y la descarga en .terraform/. |
(signed by HashiCorp) | El plugin está firmado: tienes el provider real. |
Terraform has created a lock file .terraform.lock.hcl | La versión elegida se anota en un archivo que hay que guardar en Git: el próximo init, en casa de un colega, tomará la misma. |
Terraform has been successfully initialized! | La frase que hay que esperar. |
Aparecieron dos cosas en tu carpeta: el directorio oculto .terraform/ (el provider descargado, unos 18 MB en la máquina del curso, que nunca debe subirse a Git) y el archivo .terraform.lock.hcl (22 líneas, que sí debe subirse a Git). Los verás en el anexo, paso A.6 o B.6.
El equivalente conocido: npm install o pip install -r requirements.txt. Se lee una lista de dependencias, se descarga, se fijan las versiones (package-lock.json).
Terraform se niega a continuar y te dice qué hacer. terraform plan sin init responde:
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 inity terraform validate sin 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 initEn ambos casos, la última línea es la solución. init puede relanzarse sin riesgo tantas veces como quieras; nunca toca tus recursos.
terraform fmtLo que pide el comando: «Realinea los espacios y la indentación de mis archivos .tf según el estilo oficial.»
Una sola novedad: la salida vacía. fmt muestra el nombre de cada archivo que modificó; si pegaste el código tal cual, no tiene nada que corregir y no muestra nada. No es un error, es la mejor respuesta posible. Si hubieras indentado mal una línea, habría mostrado main.tf y reescrito el archivo.
El equivalente conocido: prettier --write, black, gofmt. El kit verifica este punto con terraform fmt -check -recursive, que no modifica nada y sale en error (código 3) si un archivo no está en el formato correcto.
terraform validateSuccess! The configuration is valid.Lo que pide el comando: «Relee mis bloques. ¿Existen los nombres de argumentos, están cerradas las llaves, apuntan las referencias a algo?»
Una sola novedad: Terraform consulta al provider para conocer los argumentos válidos de un local_file. Por eso validate exige init antes. No lee el state, no contacta ninguna API, no crea nada. La frase que hay que esperar: Success! The configuration is valid.
Lo que detecta: contenu en lugar de content (An argument named "contenu" is not expected here. Did you mean "content"?), una llave olvidada (Error: Unclosed configuration block), una comilla sin cerrar (Error: Unterminated template string), un tipo inexistente (The provider hashicorp/local does not support resource type "local_fichier".). El anexo C los retoma uno por uno.
Lo que no detecta: una ruta que no existe, un nombre de bucket ya tomado, una mala arquitectura. validate dice «esto es HCL correcto», no «esto es una buena idea».
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.Lo que pide el comando: «Compara lo que describe mi código con lo que ya sabes, y dime qué harías, sin hacerlo.»
Una sola novedad: el presupuesto. Nada se ha creado; message.txt todavía no existe. Léelo de arriba a abajo:
| Línea | Cómo leerla |
|---|---|
+ create | La leyenda: en este plan, solo hay creaciones. |
# local_file.message will be created | La dirección del recurso (tipo . nombre) y su destino. |
+ resource "local_file" "message" { | El bloque entero está precedido de un +: todo es nuevo. |
+ content = "Bonjour, …" | Un atributo que escribiste: Terraform conoce su valor. |
+ content_md5 = (known after apply) | Un atributo que el provider calculará después de la creación: la huella del contenido. Terraform no puede adivinarla antes. |
+ directory_permission = "0777" | Un atributo que no escribiste: el provider tiene un valor por defecto. |
+ filename = "./message.txt" | Tu ${path.module}/message.txt, resuelto. |
Plan: 1 to add, 0 to change, 0 to destroy. | La línea que hay que leer primero, siempre. Una creación, ninguna modificación, ninguna destrucción. |
Note: You didn't use the -out option… | Información: este presupuesto no se guarda; apply calculará otro. Sin importancia aquí. |
El equivalente conocido: git diff antes de git commit, o el modo «simulación» (--dry-run, -WhatIf) de un script. La diferencia: un script --dry-run te muestra lo que va a hacer; terraform plan te muestra lo que falta entre el código y lo real, después de haber releído lo real.
El provider local expone, para un local_file, todo lo que sabe calcular: seis huellas del contenido (md5, sha1, sha256, sha512, y dos versiones codificadas en base64), los permisos, el identificador. Solo escribiste dos (filename, content); los demás son atributos que el provider completa. Es lo mismo para un bucket S3: escribes tres líneas, el plan muestra treinta (ARN, región, identificador del propietario…). Aprende a reconocer los tuyos y a pasar por encima de los demás, excepto la última línea Plan:, que nunca se pasa por alto.
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.Lo que pide el comando: «Recalcula el presupuesto, muéstramelo, y si respondo yes, hazlo.»
Una sola novedad: la pregunta. Terraform se detiene en Enter a value: y espera. Escribe yes completo, luego Enter. y, Y, oui o una línea vacía dan Apply cancelled. y nada se toca: es una protección, no un error. Luego tres líneas: Creating..., Creation complete after 0s [id=…] (el identificador que el plan anunciaba como (known after apply) ahora se conoce), y la frase que hay que esperar: Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Los tres números son los del plan.
Ahora, message.txt existe en tu carpeta, y apareció un nuevo archivo al lado: terraform.tfstate. Ve a verificarlo con tu anexo (A.6 o B.6) antes de continuar: el archivo contiene efectivamente Bonjour, ce fichier a été créé avec Terraform.
El equivalente conocido: un script que escribe el archivo, Set-Content o echo > message.txt. La diferencia: el script escribe y olvida; Terraform escribe y anota en su registro que escribió, con qué identificador, con qué contenido.
terraform state listlocal_file.messageLo que pide el comando: «Lista todo lo que gestionas en esta carpeta.»
Una sola novedad: el state se lee. Una línea, un recurso: la dirección local_file.message, la misma que en el plan. Esta línea prueba que Terraform vinculó el bloque de tu código con el archivo real: es lo que le permitirá modificarlo o destruirlo más tarde sin que tengas que decirle de nuevo cuál es.
Antes de apply, el mismo comando respondía No state file was found!: el registro todavía no existía. Después de destroy (T12), ya no responderá nada en absoluto.
El equivalente conocido: docker ps, kubectl get pods, aws s3 ls. «¿Qué está corriendo, qué existe?» Solo que state list no va a ver lo real: lee su cuaderno.
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"
}Lo que pide el comando: «Muéstrame todo lo que sabes del recurso local_file.message.»
Una sola novedad: el comando toma un parámetro, la dirección leída en T7. Compara con el plan de T5: todos los valores (known after apply) ahora están completados. El id es la huella SHA-1 del contenido, el mismo valor que content_sha1 y que el [id=…] que muestra apply. Es el registro del arquitecto, pieza por pieza.
Si te equivocas de dirección (local_file.mesage), Terraform responde No instance found for the given address! y te remite a terraform state list.
El archivo terraform.tfstate es JSON: un número de serie ("serial"), la versión de Terraform, y una lista "resources" donde cada recurso tiene exactamente los atributos que state show te muestra. Puedes abrirlo para leerlo. Nunca lo modificas a mano: una coma desplazada, y Terraform ya no reconoce lo que construyó, o cree gestionar algo que ya no existe. Para actuar sobre el state, existen comandos (terraform state rm, terraform state mv, terraform import) que verás en el módulo 4.
Otras dos reglas, desde hoy. El state puede contener secretos (aquí, el texto del archivo; en otros casos, una contraseña de base de datos): no se comparte por mensaje ni se sube a Git. Y es la memoria de Terraform: si lo eliminas, Terraform cree que nada existe y propone recrear todo, mientras que los recursos siguen ahí y, en el cloud, siguen siendo facturados.
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.Lo que pide el comando: «Muestra los valores que el código eligió exponer con bloques output.»
Una sola novedad: una advertencia (Warning), no un error. Tu main.tf no tiene ningún bloque output, así que Terraform no tiene nada que mostrar y te lo dice. Escribirás tus primeros outputs en el proyecto 02; aquí, el comando sirve para ver la diferencia entre «esto falló» (Error:) y «no hay nada que mostrar» (Warning:).
Abre main.tf, reemplaza la línea content por esta, guarda:
content = "Deuxième version du fichier créée avec Terraform."Luego:
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.Lo que pide el comando: lo mismo que en T5. Pero esta vez Terraform tiene un registro con el que comparar.
Una sola novedad: el símbolo -/+, «destruir y luego recrear». Tres pistas te lo dicen, y hay que saber identificarlas:
| Pista | Dónde | Qué dice |
|---|---|---|
must be replaced | el título # local_file.message must be replaced | No es will be updated in-place. |
# forces replacement | al final de la línea ~ content = "…" -> "…" | Es este atributo el que obliga a reemplazar. El ~ delante dice que el valor cambia; el comentario dice que este cambio no puede hacerse en el lugar. |
Plan: 1 to add, 0 to change, 1 to destroy. | la última línea | Una destrucción y una creación, cero modificación. |
Mira también la primera línea, nueva: Refreshing state... [id=…]. Antes de comparar, Terraform fue a releer el archivo real para verificar que todavía corresponde a su registro. Ahí es donde detectaría una deriva (lección 01), si hubieras modificado message.txt a mano.
La diferencia esencial entre
~y-/+. Para un archivo de texto, ser reemplazado o modificado en el lugar da lo mismo: al final, el contenido es el nuevo. Para una base de datos, un disco o un usuario,-/+significa pérdida del objeto y de su identificador: los datos del disco, la contraseña del usuario, la dirección IP del servidor. Es el provider quien decide, atributo por atributo, qué fuerza un reemplazo; tú lo lees en el plan antes de deciryes. El providerlocalreemplaza el archivo en cuantocontentcambia: nunca un~solo para este atributo.
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.Lo que pide el comando: lo mismo que en T6.
Nada nuevo en el comando; todo está en la salida. Cuatro líneas de acción en lugar de dos: Destroying..., Destruction complete, luego Creating..., Creation complete. El orden es el del símbolo -/+: primero lo menos, luego lo más. Y el identificador cambió (ff6b93dc… antes, 1df9196a… después): es otro objeto, no el mismo modificado. Verifica el nuevo contenido con tu anexo (A.8 o B.8): Deuxième version du fichier créée avec Terraform.
Balance de T5 a T11: viste los dos presupuestos que releerás toda tu carrera: + (crear) y -/+ (reemplazar). El tercero, ~ (modificar en el lugar), no existe para el content de un local_file; lo encontrarás en los proyectos cloud, por ejemplo cuando una etiqueta (tag) cambia en un recurso 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.Lo que pide el comando: «Destruye todo lo que gestionas en esta carpeta, y muéstrame el presupuesto antes.»
Una sola novedad: el símbolo - solo, y una pregunta más grave: Do you really want to destroy all resources? … There is no undo. Cada atributo pasa a -> null: ya no quedará nada. La frase que hay que esperar: Destroy complete! Resources: 1 destroyed. El archivo message.txt desapareció de tu carpeta.
Es el comando que cierra cada sesión de este curso. Aquí borra un archivo de texto; en el proyecto 03 eliminará un bucket que, de lo contrario, seguiría facturándose.
terraform state listLo que pide el comando: lo mismo que en T7.
Nada nuevo, y una salida vacía: Terraform ya no gestiona nada en esta carpeta. El archivo terraform.tfstate todavía existe, pero su lista "resources" es [], y apareció un terraform.tfstate.backup al lado (la versión de antes del destroy, que Terraform guarda por precaución). Tu anexo (A.9 y A.10, o B.9 y B.10) te hace listar la carpeta y lanzar etat para la prueba final: Ressources encore gérées : 0 (0 attendu à la fin d'une séance).
Balance de T1 a T13: init una vez, luego fmt, validate, plan, apply, state list, state show, un plan y un apply de modificación, destroy, state list. Trece comandos, cinco frases que reconocer: successfully initialized!, The configuration is valid., Plan: N to add, N to change, N to destroy., Apply complete!, Destroy complete!.
El mensaje que hay que retener. Un script PowerShell o bash habría escrito
message.txten una línea, y lo habría eliminado en otra. Lo que el script no hace y que viste hacer a Terraform: anunciar antes de actuar (plan), pedir un acuerdo explícito (yes), anotar lo que creó (state list), releer lo real antes de cada decisión (Refreshing state...), distinguir modificar de reemplazar (-/+), y saber deshacer todo sin que se le tenga que repetir qué.
El proyecto 01 no toca AWS. Pero el proyecto 03 crea un bucket S3 real, y necesitarás una cuenta lista. Esta sección se hace en el navegador, es idéntica en Windows, Linux y macOS, y puedes hacerla antes o después del ciclo Terraform de este proyecto. Los comandos aws configure y aws sts get-caller-identity que la acompañan están en tu anexo (A.2 o B.2).
Si trabajas en AWS Academy, AWS Educate, un sandbox proporcionado por la escuela o una cuenta temporal de laboratorio: usa las credenciales proporcionadas por la plataforma y pasa directamente al paso A.2 o B.2 (caso «Academy»). No crees un usuario IAM si tu profesor ya te da accesos temporales.
ca-central-1 si el laboratorio no impone otra.La cuenta root sirve únicamente para crear la cuenta, gestionar la facturación y hacer las operaciones sensibles. Activa el MFA (autenticación de dos factores) en la cuenta root, luego crea un usuario separado para el trabajo de laboratorio, a continuación.
IAM y abre el servicio IAM.terraform-admins.AdministratorAccess, marca la política AdministratorAccess.Solo para un laboratorio.
AdministratorAccessotorga acceso completo a todos los servicios y recursos de la cuenta. Es práctico para aprender; no es un modelo de seguridad para producción, donde se le dan a Terraform solo los permisos que necesita (módulo 4).
terraform-admin.terraform-admins → Next → Create user.terraform-admin.aws-cli-terraform-lab → Create access key..csv o copia Access key y Secret access key en un gestor de contraseñas. La Secret access key nunca volverá a mostrarse.Lo que nunca debe hacerse. Nunca pegues una Access Key, una Secret Access Key, un token de sesión, un archivo
.envo unterraform.tfstateen GitHub, Word, Teams, Discord, Slack, un ticket o un correo. Estos elementos dan acceso a la cuenta. Si una clave se filtra: IAM → el usuario → Security credentials → Deactivate y luego Delete, y se crea otra.
Antes de relanzar terraform destroy una segunda vez en una carpeta ya destruida, escribe en papel lo que dirá la última línea del plan. Luego lánzalo. Después, recrea el archivo con terraform apply, abre message.txt en VS Code, añade una palabra a mano, guarda, y escribe terraform plan: ¿qué dice la línea Refreshing state..., qué símbolo aparece, y cómo se llama esta diferencia en la lección 01? Termina con destroy: la carpeta debe volver a Ressources encore gérées : 0.
Todos los comandos de este anexo se escriben en PowerShell (Windows Terminal o PowerShell 7), con .\labo.ps1 …. Las salidas reproducidas son las de la máquina del curso, en Windows 11 y Terraform 1.12.2.
git --version responde), VS Code instalado con el comando code disponible en PowerShell (si no: VS Code → Ctrl+Shift+P → «Shell Command: Install 'code' command in PATH», o reinstala marcando «Add to PATH»)..\labo.ps1 («la ejecución de scripts está deshabilitada en este sistema»): Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, responde O, vuelve a lanzar. Una sola vez por máquina..\labo.ps1 etat debe mostrar Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Lo más simple, con el gestor de paquetes de Windows:
winget install Hashicorp.TerraformCierra PowerShell, vuelve a abrirlo, luego:
terraform versionPunto de control:
Terraform v1.12.2
on windows_amd64Tu versión puede ser más reciente; todo lo que sea 1.6 o superior es válido. Si Terraform añade Your version of Terraform is out of date!, es información, no un error.
Sin winget, con el binario oficial: ve a https://developer.hashicorp.com/terraform/install, elige Windows, descarga la versión AMD64, descomprime el .zip, crea la carpeta C:\terraform, mueve terraform.exe ahí, luego añade C:\terraform al PATH: menú Inicio → «variables de entorno» → Editar las variables de entorno del sistema → Variables de entorno → en Variables del sistema, selecciona Path → Editar → Nuevo → C:\terraform → Aceptar. Cierra todas las ventanas de PowerShell, vuelve a abrir, escribe de nuevo terraform version.
Si ves algo distinto: terraform : Le terme «terraform» n'est pas reconnu comme nom d'applet de commande… → Terraform no está en el PATH, o PowerShell no se reinició después de la instalación. Anexo C.
El proyecto 01 no usa AWS; este paso prepara el proyecto 03. Puedes hacerlo ahora o dejarlo para más tarde.
.msi: Next, acepta la licencia, mantén la carpeta por defecto, Install.aws --versionPunto de control: una versión que empieza con aws-cli/2 (en la máquina del curso: aws-cli/2.22.18). Si ves aws-cli/1, es la versión antigua: desinstálala.
Luego configura las claves creadas en la sección La consola AWS, en el navegador:
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]: jsonVerifica que la CLI hable bien con AWS:
aws sts get-caller-identityEjemplo de respuesta (los valores son los de tu cuenta):
{
"UserId": "AIDA...",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/terraform-admin"
}Caso AWS Academy o sandbox temporal: abre el laboratorio, haz clic en AWS Details o Credentials, copia Access Key, Secret Key y Session Token (obligatorio con accesos temporales), luego:
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-identityUbícate en la carpeta donde guardas tus proyectos (por ejemplo C:\Users\<tú>\Documents), luego:
git clone https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr.git lab-terraform
cd lab-terraform
dirPunto de control: dir lista projets, labo.ps1, labo.sh, README.md (y .gitattributes, .gitignore con dir -Force). Luego:
.\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.Las cuatro herramientas requeridas son terraform, aws, git y code. gh, az y gcloud son opcionales y pueden estar ABSENT sin consecuencia antes del módulo 3. Si aws está ABSENT porque dejaste A.2 para más tarde, la última línea dice 3 outils requis présents sur 4: puedes continuar este proyecto igualmente.
.\labo.ps1 nouveau projet-01-localDossier travail\projet-01-local créé (ignoré par Git). Tapez :
cd travail\projet-01-localHaz lo que el script te indica, luego abre la carpeta en VS Code:
cd travail\projet-01-local
code .La carpeta travail\ está ignorada por Git: puedes escribir libremente en ella sin ensuciar el kit. El corregido queda en projets\01-terraform-local\.
Si code . no hace nada: abre VS Code a mano, File → Open Folder, y elige lab-terraform\travail\projet-01-local.
main.tfEn VS Code: icono New File en el explorador de la izquierda, nombra el archivo main.tf (atención: no main.tf.txt, VS Code no añade extensión pero el Bloc de notas de Windows sí lo haría), pega el código de la sección El código: archivo por archivo, guarda con Ctrl+S.
Verifica desde PowerShell:
Get-Content .\main.tfPunto de control: las quince líneas del archivo, de terraform { a }. Luego:
Get-ChildItemUna sola entrada: main.tf. Si ves main.tf.txt, renombra: Rename-Item main.tf.txt main.tf.
Recorre T2 a T6 de la sección Terraform, en la terminal:
terraform init
terraform fmt
terraform validate
terraform plan
terraform applyResponde yes a la pregunta de apply. Puntos de control, en orden: Terraform has been successfully initialized!, nada para 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.
Verifica lo que apareció en la carpeta:
Get-ChildItem -Force.terraform
.terraform.lock.hcl
main.tf
message.txt
terraform.tfstate(-Force también muestra las entradas ocultas, las que empiezan con un punto; sin él, solo verías main.tf, message.txt y terraform.tfstate.) Cinco entradas:
| Entrada | Quién la creó | Qué es |
|---|---|---|
.terraform | init | Carpeta oculta, el provider descargado. Nunca en Git. |
.terraform.lock.hcl | init | Las versiones de providers elegidas. En Git. |
main.tf | tú | El código. |
message.txt | apply | El recurso. |
terraform.tfstate | apply | El state, el registro. Nunca en Git, nunca compartido. |
Lee el archivo creado:
Get-Content .\message.txtBonjour, ce fichier a été créé avec Terraform.También puedes verificarlo en el explorador de Windows: abre la carpeta lab-terraform\travail\projet-01-local, haz doble clic en message.txt.
Recorre T7, T8 y T9:
terraform state list
terraform state show local_file.message
terraform outputPuntos de control: local_file.message; el bloque completo con filename = "./message.txt" y un id de cuarenta caracteres; Warning: No outputs found.
Si tienes curiosidad, mira el state en sí, sin modificarlo:
Get-Content .\terraform.tfstateJSON con "serial", "terraform_version": "1.12.2" y una lista "resources" que contiene local_file.message. Vuelve a cerrarlo. Nunca se edita a mano.
En VS Code, reemplaza la línea content de main.tf por:
content = "Deuxième version du fichier créée avec Terraform."Guarda, luego recorre T10 y T11:
terraform plan
terraform applyResponde yes. Puntos de control: # local_file.message must be replaced, # forces replacement al final de la línea content, Plan: 1 to add, 0 to change, 1 to destroy., luego Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
Get-Content .\message.txtDeuxième version du fichier créée avec Terraform.Recorre T12 y T13:
terraform destroy
terraform state listResponde yes. Puntos de control: Destroy complete! Resources: 1 destroyed., luego una salida vacía para state list.
Get-ChildItem -Force.terraform
.terraform.lock.hcl
main.tf
terraform.tfstate
terraform.tfstate.backupmessage.txt desapareció. terraform.tfstate sigue ahí pero ya no contiene ningún recurso; terraform.tfstate.backup es la copia de antes del destroy. .terraform y .terraform.lock.hcl permanecen: es normal, te servirán si relanzas apply.
Vuelve a la raíz del kit y lanza 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 hubieras olvidado el destroy, la salida diría travail projet-01-local : 1 ressource dans le state y luego Ressources encore gérées : 1 (0 attendu à la fin d'une séance).: es el guardián que lanzarás al final de cada sesión, cuando los recursos se estén facturando.
Para empezar de nuevo desde cero, en lugar de limpiar la carpeta: .\labo.ps1 nouveau projet-01-reprise, y partes de una carpeta vacía.
Todos los comandos de este anexo se escriben en una terminal bash (o zsh en macOS), con ./labo.sh …. Las salidas de Terraform son las de la máquina del curso (Terraform 1.12.2); las salidas de ls -la se capturaron en Git Bash, las columnas de permisos, propietario y fecha difieren en tu caso.
git --version responde), VS Code instalado con el comando code disponible en la terminal (en macOS: VS Code → Cmd+Shift+P → «Shell Command: Install 'code' command in PATH»)../labo.sh responde Permission denied: chmod +x labo.sh, una sola vez../labo.sh etat debe mostrar Ressources encore gérées : 0 (0 attendu à la fin d'une séance).Sigue la página oficial https://developer.hashicorp.com/terraform/install para tu sistema. En resumen:
apt con la clave GPG, comandos copiados de la página oficial), luego sudo apt-get install terraform.brew tap hashicorp/tap luego brew install hashicorp/tap/terraform..zip Linux AMD64 (o ARM64), unzip, luego sudo mv terraform /usr/local/bin/.winget), Git Bash lo ve en el PATH.Cierra la terminal, vuelve a abrirla, luego:
terraform versionPunto de control: Terraform v1.12.2 (o más reciente) seguido de on linux_amd64, on darwin_arm64 o on windows_amd64 según tu máquina. Todo lo que sea 1.6 o superior es válido.
Si ves algo distinto: bash: terraform: command not found → el binario no está en una carpeta del PATH (echo $PATH), o la terminal no se volvió a abrir. Anexo C.
El proyecto 01 no usa AWS; este paso prepara el proyecto 03. Puedes hacerlo ahora o dejarlo para más tarde.
Sigue https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html para tu sistema (paquete .zip con ./aws/install en Linux, .pkg en macOS). Luego:
aws --versionPunto de control: una versión que empieza con aws-cli/2. Si ves aws-cli/1, es la versión antigua: desinstálala.
Configura las claves creadas en la sección La consola AWS, en el navegador:
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]: jsonVerifica que la CLI hable bien con AWS:
aws sts get-caller-identityEjemplo de respuesta (los valores son los de tu cuenta):
{
"UserId": "AIDA...",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/terraform-admin"
}Caso AWS Academy o sandbox temporal: abre el laboratorio, haz clic en AWS Details o Credentials, copia Access Key, Secret Key y Session Token (obligatorio con accesos temporales), luego:
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-identityUbícate en la carpeta donde guardas tus proyectos (por ejemplo ~/projets), luego:
git clone https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr.git lab-terraform
cd lab-terraform
lsPunto de control: ls lista labo.ps1 labo.sh projets README.md (y .gitattributes, .gitignore con ls -a). Luego:
./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.(Salida capturada en Git Bash, de ahí el git 2.49.0.windows.1; en Linux leerás tu propia versión de Git.) Las cuatro herramientas requeridas son terraform, aws, git y code. gh, az y gcloud son opcionales y pueden estar ABSENT sin consecuencia antes del módulo 3. Si aws está ABSENT porque dejaste B.2 para más tarde, la última línea dice 3 outils requis présents sur 4: puedes continuar este proyecto igualmente.
./labo.sh nouveau projet-01-localDossier travail/projet-01-local créé (ignoré par Git). Tapez :
cd travail/projet-01-localHaz lo que el script te indica, luego abre la carpeta en VS Code:
cd travail/projet-01-local
code .La carpeta travail/ está ignorada por Git: puedes escribir libremente en ella sin ensuciar el kit. El corregido queda en projets/01-terraform-local/.
Si code . no hace nada: abre VS Code a mano, File → Open Folder, y elige lab-terraform/travail/projet-01-local.
main.tfEn VS Code: icono New File en el explorador de la izquierda, nombra el archivo main.tf, pega el código de la sección El código: archivo por archivo, guarda con Ctrl+S (Cmd+S en macOS).
Tercer camino, sin editor, si prefieres la 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(Las comillas alrededor de 'EOF' evitan que bash interprete ${path.module}: sin ellas, la línea filename quedaría vacía.) Verifica:
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.tfPunto de control: las quince líneas del archivo, y una sola entrada en la carpeta, main.tf, de unos 286 bytes.
Recorre T2 a T6 de la sección Terraform, en la terminal:
terraform init
terraform fmt
terraform validate
terraform plan
terraform applyResponde yes a la pregunta de apply. Puntos de control, en orden: Terraform has been successfully initialized!, nada para 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.
Verifica lo que apareció en la carpeta:
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 también muestra las entradas ocultas, las que empiezan con un punto; -l da el detalle.) Cinco entradas además de . y ..:
| Entrada | Quién la creó | Qué es |
|---|---|---|
.terraform | init | Carpeta oculta, el provider descargado. Nunca en Git. |
.terraform.lock.hcl | init | Las versiones de providers elegidas. En Git. |
main.tf | tú | El código. |
message.txt | apply | El recurso. 50 bytes: el texto, sin salto de línea final. |
terraform.tfstate | apply | El state, el registro. Nunca en Git, nunca compartido. |
Lee el archivo creado:
cat message.txtBonjour, ce fichier a été créé avec Terraform.(El archivo no tiene salto de línea final: tu indicador de línea de comandos puede aparecer pegado al final de la frase. Es normal.)
Recorre T7, T8 y T9:
terraform state list
terraform state show local_file.message
terraform outputPuntos de control: local_file.message; el bloque completo con filename = "./message.txt" y un id de cuarenta caracteres; Warning: No outputs found.
Si tienes curiosidad, mira el state en sí, sin modificarlo:
cat terraform.tfstateJSON con "serial", "terraform_version": "1.12.2" y una lista "resources" que contiene local_file.message. Vuelve a cerrarlo. Nunca se edita a mano.
En VS Code, reemplaza la línea content de main.tf por:
content = "Deuxième version du fichier créée avec Terraform."Guarda, luego recorre T10 y T11:
terraform plan
terraform applyResponde yes. Puntos de control: # local_file.message must be replaced, # forces replacement al final de la línea content, Plan: 1 to add, 0 to change, 1 to destroy., luego Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
cat message.txtDeuxième version du fichier créée avec Terraform.Recorre T12 y T13:
terraform destroy
terraform state listResponde yes. Puntos de control: Destroy complete! Resources: 1 destroyed., luego una salida vacía para 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 desapareció. terraform.tfstate pasó de 1667 a 181 bytes: ya no contiene ningún recurso; terraform.tfstate.backup (1667 bytes) es la copia de antes del destroy. .terraform y .terraform.lock.hcl permanecen: es normal, te servirán si relanzas 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": []: el registro está vacío. Tu lineage (el identificador único de este state) será diferente.
Vuelve a la raíz del kit y lanza 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 hubieras olvidado el destroy, la salida diría travail projet-01-local : 1 ressource dans le state y luego Ressources encore gérées : 1 (0 attendu à la fin d'une séance).: es el guardián que lanzarás al final de cada sesión, cuando los recursos se estén facturando.
Para empezar de nuevo desde cero, en lugar de limpiar la carpeta: ./labo.sh nouveau projet-01-reprise, y partes de una carpeta vacía.
Cada caso: el mensaje exacto → la causa → el gesto.
terraform plan responde Error: Inconsistent dependency lock file … required by this configuration but no version is selected → No lanzaste terraform init en esta carpeta (o añadiste un provider desde entonces). El mensaje termina con la solución: terraform init, y vuelve a lanzar.
terraform validate responde Error: Missing required provider … You may be able to install it automatically by running: terraform init → Misma causa, mismo gesto: terraform init.
Error: Unsupported argument … An argument named "contenu" is not expected here. Did you mean "content"? → Error de tipeo en un nombre de argumento. Terraform a menudo propone la palabra correcta. Corrige, vuelve a guardar, relanza validate.
Error: Unclosed configuration block … There is no closing brace for this block before the end of the file. → Falta una llave }. Cuéntalas: cada { tiene su }. En main.tf, hay tres pares anidados para el bloque terraform, uno para provider, uno para resource.
Error: Invalid multi-line string luego Error: Unterminated template string … No closing marker was found for the string. → Falta una comilla " al final de un valor. La línea culpable se cita (3: content = "Bonjour Terraform).
Error: Invalid resource type … The provider hashicorp/local does not support resource type "local_fichier". → El tipo de recurso no existe en este provider. Los tipos del provider local se llaman local_file y local_sensitive_file; la documentación del provider en el Registry da la lista.
Error: Invalid Attribute Combination … No attribute specified when one (and only one) of [content,sensitive_content,content_base64] is required (repetido cuatro veces) → Quitaste la línea content: un local_file debe decir qué contiene. Vuelve a ponerla.
terraform validate dice Success! pero terraform plan responde Error: No configuration files … create a Terraform configuration file (.tf file) and try again. → No hay ningún archivo .tf en la carpeta: o no estás en travail/projet-01-local (verifica con pwd), o el archivo se llama main.tf.txt. Renómbralo a main.tf. Una carpeta vacía es una configuración válida (vacía), de ahí el Success! engañoso.
terraform apply responde Apply cancelled. y nada se crea → Escribiste algo distinto de yes (por ejemplo y, Y, oui, o solo Enter). Vuelve a lanzar y escribe yes completo.
terraform state list responde No state file was found! → Todavía no se hizo ningún apply en esta carpeta, o no estás en la carpeta correcta. No es una falla: todavía no hay nada que listar.
terraform state show responde No instance found for the given address! → La dirección está mal escrita, o el recurso fue destruido. terraform state list da las direcciones exactas.
terraform fmt -check sale en error (código 3) mostrando main.tf → El archivo no está en el formato oficial (indentación, alineación de los =). No es un error de sintaxis: terraform fmt sin -check lo corrige.
Después de destroy, terraform.tfstate sigue ahí y crees que el destroy falló → No: ábrelo, "resources": []. El archivo permanece, vacío, con un terraform.tfstate.backup al lado. Destroy complete! Resources: 1 destroyed. es la prueba.
.\labo.ps1 etat o ./labo.sh etat muestra Ressources encore gérées : 1 → Se olvidó un destroy en una de las carpetas listadas arriba (travail projet-01-local : 1 ressource dans le state). Ve a esa carpeta, terraform destroy, yes, vuelve a lanzar etat.
Solo Windows — terraform : Le terme «terraform» n'est pas reconnu comme nom d'applet de commande, fonction, fichier de script ou programme exécutable. → Terraform no está en el PATH, o PowerShell no se reinició después de la instalación. Cierra todas las ventanas de PowerShell, vuelve a abrir, escribe de nuevo terraform version. Si persiste, anexo A.1 (agregar C:\terraform al PATH).
Solo Windows — aws : Le terme «aws» n'est pas reconnu… → AWS CLI no está instalado o PowerShell no se reinició. Reinstala AWS CLI versión 2 (A.2), cierra y vuelve a abrir PowerShell, escribe de nuevo aws --version.
Solo Windows — .\labo.ps1 es rechazado: «la ejecución de scripts está deshabilitada en este sistema» → Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, responde O, vuelve a lanzar. Una sola vez por máquina.
Solo Windows — el archivo se llama main.tf.txt → El Bloc de notas añade .txt. En PowerShell: Rename-Item main.tf.txt main.tf. Usa VS Code para crear los archivos.
Linux nativo y macOS — bash: terraform: command not found → El binario no está en una carpeta del PATH. sudo mv terraform /usr/local/bin/, o verifica la instalación por paquete (B.1). Vuelve a abrir la terminal.
macOS y bash — ./labo.sh responde Permission denied → chmod +x labo.sh, una sola vez. Si bash: ./labo.sh: /bin/bash^M: bad interpreter, el archivo tiene finales de línea de Windows: git config core.autocrlf input y vuelve a clonar, o sed -i 's/\r$//' labo.sh (sed -i '' … en macOS).
aws sts get-caller-identity responde AccessDenied o InvalidClientTokenId → La clave configurada no es la correcta, o el token de sesión de Academy expiró. aws configure con la clave de terraform-admin (verifica que el usuario esté en terraform-admins con AdministratorAccess), o vuelve a hacer aws configure set … con nuevas credenciales de Academy. Sin efecto en el proyecto 01, que no llama a AWS.
Una carpeta comprimida o un repositorio Git que contenga:
main.tf (el archivo final, con la segunda versión de content);sorties.txt: la salida completa de terraform plan (primera versión), de terraform state list después de apply, del terraform plan de modificación (el que tiene must be replaced), y de terraform state list después de destroy (vacío);README.md según el modelo a continuación.No entregues ni la carpeta .terraform/, ni terraform.tfstate, ni ninguna Access Key.
# Proyecto 01 — Terraform local
- Terraform: (salida de `terraform version`)
- Sistema: Windows / Linux / macOS
## Lo que hice
init, fmt, validate, plan, apply, state list, state show, modificación de content, plan, apply, destroy, state list.
## El archivo terraform.tfstate, en tres líneas propias
(Para qué sirve. Por qué Terraform lo necesita para destroy. Por qué no se edita ni se comparte.)
## Qué me bloqueó, y cómo lo resolví
(Una línea, o «nada».)init, fmt, validate, plan, apply, state, destroy): https://developer.hashicorp.com/terraform/cli/commandshashicorp/local, recurso local_file: https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/fileAdministratorAccess: https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess.htmlFrase para recordar: Terraform no hace clic en la consola en tu lugar. Lee tu código, lo compara con su state y con lo real, te anuncia lo que va a cambiar, y luego crea, reemplaza o destruye para alcanzar el estado solicitado.