Blocs HCL Terraform : syntaxe, terraform, provider et resource
À la fin de ce tutoriel, vous saurez lire et écrire la syntaxe HCL de base : arguments, blocs, commentaires, puis les blocs
terraform,provideretresource, avec un aperçu devariable/output/localsetdata, une organisation multi-fichiers propre, et un lab minimal en Regionca-central-1validé parfmt/validate.Niveau : Débutant · Temps estimé : 30–40 min · Versions testées : Terraform 1.16.2 (série ≥ 1.9), AWS provider ~> 5.0 · Dernière vérification : 2026-09-10
Slug proposé :
terraform-blocs-hcl· Série : Terraform · Remplace / fusionne : #1620, #1607
Prérequis
- Avoir suivi Découvrir Terraform (
terraform-overview) — IaC, state, providers - Avoir suivi Installer Terraform (
installer-terraform) : binaire ≥ 1.9, profil AWS prêt - Avoir suivi Workflow Terraform (
terraform-workflow) :init→plan→apply→destroy - AWS CLI v2 :
aws sts get-caller-identityOK avec votre profil de lab
Coût estimé : 0 € dans ce tuto si vous vous arrêtez à fmt / validate (recommandé). Un apply éventuel créerait un bucket S3 (Free Tier / faible coût) : dans ce cas, destroy obligatoire. Aucun secret dans le HCL.
Auth sans secrets. Utilisez
AWS_PROFILE/ SSO comme dans Install et Workflow. Jamais d'access_keydans les.tf.
Ce que nous allons construire
Lab blocs HCL (ca-central-1)
├── versions.tf → bloc terraform (required_version + required_providers)
├── providers.tf → bloc provider "aws"
├── main.tf → resource S3 + tags (+ aperçu locals)
├── variables.tf / outputs.tf (aperçu, détail = tutos suivants)
├── terraform init → fmt → validate
└── Lecture des erreurs HCL fréquentes (virgules, guillemets, labels)
(Schéma à remplacer par une image locale Excalidraw / draw.io, alt : « Blocs HCL Terraform : terraform, provider, resource et fichiers ».)
Fusion de #1620 et #1607 : syntaxe HCL + blocs essentiels, sans répéter apply/destroy du Workflow.
Étape 1 — HCL en bref : arguments, blocs, commentaires
HCL (HashiCorp Configuration Language) est le langage des fichiers .tf. Trois idées suffisent pour démarrer.
1. Arguments — paire nom = valeur à l'intérieur d'un bloc :
region = "ca-central-1"
bucket = "mon-bucket-exemple"
Les chaînes utilisent des guillemets doubles. Les nombres et booléens (true / false) n'en ont pas. Les listes et maps s'écrivent avec [] et {}.
2. Blocs — structure nommée avec des accolades. Un bloc a un type, éventuellement un ou deux labels, puis un corps d'arguments (et parfois de blocs imbriqués) :
# type label1 label2
resource "aws_s3_bucket" "lab_hcl" {
bucket = "deh-lab-hcl-SUFFIXE-UNIQUE"
}
3. Commentaires — # en fin de ligne, ou / … /. Expliquez le pourquoi ; jamais de secrets.
Règles utiles : 2 espaces (terraform fmt), pas de virgule entre arguments (contrairement au JSON), labels snake_case.
Étape 2 — Bloc terraform : version, providers, backend
Le bloc terraform configure le moteur lui-même, pas une ressource cloud. Placez-le typiquement dans versions.tf :
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# backend "s3" { ... } # mention : state distant — détail dans le tuto State
}
required_version: refuse un binaire trop ancien auinit(série lab ≥ 1.9).required_providers: source registry (hashicorp/aws) et contrainte (~> 5.0= 5.x compatible).backend(aperçu) : où stocker le state (local par défaut ; S3 + lock en équipe). Pas de backend distant ici — ce sera le tuto State.
Sans ce bloc, Terraform fonctionne, mais sans garde-fou de version ni reproductibilité des providers.
Étape 3 — Bloc provider
Le provider est le plugin qui parle à une API (ici AWS). Un bloc provider configure comment Terraform contacte ce cloud :
provider "aws" {
region = "ca-central-1"
# Auth via AWS_PROFILE / SSO / env — jamais access_key / secret_key ici
}
Points clés :
- Le label
"aws"correspond au nom déclaré dansrequired_providers. - La Region doit être explicite et alignée sur votre lab (
ca-central-1). - Auth via chaîne CLI (profil, env, SSO) — zéro clé en clair.
- Alias multi-Region / multi-compte : détail dans Providers et ressources.
Le provider ne crée rien seul : contexte pour resource et data.
Étape 4 — Bloc resource : type, nom local, arguments, meta-arguments
Une resource déclare un objet d'infrastructure géré par Terraform (créer, maj, détruire) :
resource "aws_s3_bucket" "lab_hcl" {
bucket = "deh-lab-hcl-SUFFIXE-UNIQUE"
tags = {
Project = "devopselastichayway"
ManagedBy = "terraform"
Stage = "hcl-blocks"
}
}
Décryptage :
| Élément | Exemple | Rôle |
|---|---|---|
| Type | aws_s3_bucket |
Famille de ressource du provider AWS |
| Nom local | lab_hcl |
Identifiant dans votre module (pas l'ID cloud) |
| Adresse | aws_s3_bucket.lab_hcl |
Référence ailleurs (id, arn, etc.) |
| Arguments | bucket, tags |
Propriétés de la ressource |
Meta-arguments (aperçu) : count, for_each, depends_on, lifecycle, provider (alias) — comportement Terraform, pas champs API AWS. Un exemplaire suffit ici ; boucles dans Loops / Dynamic blocks.
Nom local unique par type dans le module. Suffixe S3 unique : buckets globalement uniques.
Étape 5 — Aperçu variable, output et locals
Trois blocs structurants, traités en profondeur dans les tutos dédiés :
variable— entrée paramétrable (variable "environment" { type = string … }) ; évite de durcir Region / noms / tags.output— valeur exposée après apply (ex. ARN) pour humains, CI ou modules parents.locals— calculs / constantes internes (locals { common_tags = { … } }), sans polluer l'interface du module.
Exemple minimal :
variable "project" {
type = string
default = "devopselastichayway"
}
locals {
common_tags = {
Project = var.project
ManagedBy = "terraform"
}
}
output "bucket_name" {
value = aws_s3_bucket.lab_hcl.bucket
}
variables = entrée, locals = calcul interne, outputs = sortie. Types / validation / sensitive : tutos suivants.
Étape 6 — Bloc data en une phrase
Un bloc data lit une info existante (AMI, VPC, compte…) sans la créer — détail dans Data sources.
Étape 7 — Organisation multi-fichiers
Terraform charge tous les .tf du répertoire (root module) : découpage pour les humains, pas un ordre d'exécution magique.
| Fichier | Contenu typique |
|---|---|
versions.tf |
Bloc terraform (version + providers) |
providers.tf |
Blocs provider |
variables.tf |
Déclarations variable |
locals.tf |
locals partagés |
main.tf (ou fichiers par domaine) |
resource / data |
outputs.tf |
Blocs output |
Bonnes pratiques : un dossier = un lab ; .gitignore .terraform/ et .tfstate ; committer .terraform.lock.hcl ; pas d'override.tf inutile.
Étape 8 — Lab cohérent ca-central-1 : fichiers + fmt / validate
Créez le dossier et l'environnement :
mkdir -p ~/terraform-hcl-lab && cd ~/terraform-hcl-lab
export AWS_PROFILE=lab
export AWS_REGION=ca-central-1
aws sts get-caller-identity
versions.tf — bloc terraform étape 2 (>= 1.9.0, aws ~> 5.0).
providers.tf — provider AWS ca-central-1 sans clés (étape 3).
main.tf — bucket + public access block (esprit Workflow), suffixe unique :
resource "aws_s3_bucket" "lab_hcl" {
bucket = "deh-lab-hcl-SUFFIXE-UNIQUE"
tags = {
Project = "devopselastichayway"
ManagedBy = "terraform"
Stage = "hcl-blocks"
Environment = "lab"
}
}
resource "aws_s3_bucket_public_access_block" "lab_hcl" {
bucket = aws_s3_bucket.lab_hcl.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
Puis :
terraform init
terraform fmt -recursive
terraform validate
Sortie attendue : Success! The configuration is valid. Syntaxe validée sans apply obligatoire ; si apply, destroy ensuite (Workflow).
Étape 9 — Checklist syntaxe HCL
- Guillemets doubles pour les chaînes ; pas de virgules entre arguments.
- Labels
resource/data: type provider + nom localsnake_case. - Bloc
terraformavecrequired_versionetrequired_providersdès le premier projet. - Region explicite
ca-central-1; auth via profil / env / SSO. - Découpage
versions.tf/providers.tf/main.tf/variables.tf/outputs.tf. fmt+validateavant toute PR ou partage.- Variables, locals, outputs, data : aperçu seulement — détail ensuite.
- Zéro secret dans le HCL ; noms S3 uniques ; tags
Project/ManagedBy.
Nettoyage
Si vous n'avez fait que init / fmt / validate :
cd ~ && rm -rf ~/terraform-hcl-lab
Si apply : terraform destroy, vérifiez l'absence du bucket en ca-central-1, puis supprimez le dossier.
Erreurs fréquentes HCL
| Symptôme | Cause | Correction |
|---|---|---|
Erreur de parse près d'une , |
Virgule style JSON entre arguments | Supprimez les virgules ; HCL sépare par des retours ligne |
Invalid character / chaîne cassée |
Guillemets simples ou oubliés | Utilisez "…" pour les strings |
Duplicate resource / label invalide |
Même type+nom local, ou tirets / majuscules bizarres | Un seul aws_s3_bucket.lab_hcl ; snake_case |
Missing required argument |
Argument obligatoire du type resource omis | Lisez l'erreur + doc registry du type |
validate avant init |
Providers absents | terraform init d'abord |
| Confusion nom local ≠ nom cloud | lab_hcl n'est pas le bucket = "…" |
Le label est logique ; l'argument porte le nom AWS |
Clés AWS collées dans provider |
Anti-pattern | Profil / AWS_PROFILE / SSO uniquement |
Quiz (3 questions)
1. Dans resource "aws_s3_bucket" "lab_hcl", que désigne lab_hcl ?
- A. L'ID AWS définitif du bucket
- B. Le nom local dans le module Terraform
- C. La Region
ca-central-1
2. Où place-t-on typiquement required_version et required_providers ?
- A. Dans un bloc
terraform(souventversions.tf) - B. Dans le fichier
terraform.tfstate - C. Uniquement dans la console AWS
3. Quelle affirmation sur HCL est correcte ?
- A. Les arguments d'un bloc doivent être séparés par des virgules comme en JSON
- B. Les chaînes utilisent des guillemets doubles ;
fmtnormalise l'indentation - C. Le bloc
datacrée toujours une ressource facturable
Réponses : 1‑B · 2‑A · 3‑B
Pourquoi / quand solidifier les blocs HCL
Les blocs terraform, provider et resource sont le squelette de toute config. Si vous les lisez mal, variables, modules et dynamic blocks resteront flous. Revenez ici dès qu’un message d’erreur parle de « Unsupported block type » ou de labels manquants.
Pièges de syntaxe utiles à mémoriser
- Virgules style JSON dans un
.tfnatif : HCL n’en veut pas entre arguments. - Guillemets simples : préférez
"…". - Mélanger plusieurs blocs
terraformincompatibles ou plusieurs backends. - Nommer une resource avec des majuscules ou des tirets interdits : suivez les identifiants HCL.
- Secrets dans
versions.tf/providers.tf: jamais ; auth via profil, Regionca-central-1, TF ≥ 1.9.
FAQ blocs HCL
Faut-il un fichier par type de bloc ? Convention utile (versions.tf, providers.tf, main.tf), pas une obligation du moteur : Terraform fusionne tous les .tf du dossier.
locals remplace-t-il variable ? Non. variable = entrée ; locals = valeurs calculées internes.
Où déclarer le backend ? Dans le bloc terraform ; détail opérationnel dans le tuto State backend S3.
Pour aller plus loin
- Doc officielle : Configuration Language, Resources, AWS provider 5.x
- Sur ce site : enchaînez Providers et ressources, puis Variables / Locals / Outputs et Data sources
- Rappel :
validate≠ plan relu — le workflow précédent reste le filet de sécurité
Maillage série Terraform (P2)
| ← Précédent | Workflow Terraform (terraform-workflow) |
| → Suivant | Providers et ressources (terraform-providers-ressources) |
| Aussi | Variables · Découvrir Terraform (terraform-overview) |
| Carte | Overview · Install · Workflow · Blocks · Providers · Variables · Locals · Outputs · State · Data sources · Loops · Conditionals · Dynamic blocks · Modules ×2 · Workspaces · Provisioners · EBS · ELB/ALB · IAM · RDS · VPC · Auto Scaling · Route 53 |
Cas réel — un bloc terraform oublié et un provider flottant
Sans required_providers, init choisit « la dernière 5.x » un lundi et une autre le vendredi. Le lock file rattrape, mais seulement s’il est commité. Un collègue sans lock se retrouve avec un schema différent et un plan qui remplace des ressources. Déclarez source + contrainte ~> 5.0 dès le premier fichier.
Piège : mélanger un backend incomplet dans le bloc terraform « pour plus tard » et un state local. Terraform refuse souvent l’init à moitié configuré. Soit backend distant complet, soit rien — pas un backend "s3" {} vide en commentaire ambigu.
À retenir : chaque type de bloc a un rôle (réglages, provider, ressource, data, variable, output). Si vous ne savez pas dans quel bloc mettre une valeur, ce n’est probablement pas une ressource.
Retour parcours Terraform — hub de la série et leçons sœurs.



