Terraform Language Basics : types HCL et expressions
À la fin de ce tutoriel, vous maîtriserez les Terraform Language Basics centrés sur les types HCL (string, number, bool, list, map, object, set, tuple, any) et les expressions (littéraux, références, interpolations
${…}, opérateurs, fonctions courantes, conditions ternaires légères), avec le contexte fichiers.tf/ working directory — sans cloner le catalogue des blocsterraform/provider/resource(voirterraform-blocs-hcl). Labfmt/validateen Regionca-central-1.Niveau : Débutant · Temps estimé : 30–40 min · Versions testées : Terraform 1.9+, AWS provider 5.x · Dernière vérification : 2026-09-11
Prérequis
- Découvrir Terraform (
terraform-overview) — IaC, state, providers - Installer Terraform (
installer-terraform) : binaire ≥ 1.9, profil AWS prêt - Workflow Terraform (
terraform-workflow) : aperçuinit→plan→apply→destroy - Éditeur + terminal ; AWS CLI v2 optionnelle (le mini-lab s’arrête à
fmt/validate)
Coût estimé : 0 € en restant sur fmt / validate (recommandé). Aucun secret dans le HCL. Region de lab : ca-central-1.
Différenciation. Ici : types + expressions (valeurs, interpolations, opérateurs, fonctions). Le détail des types de blocs (
terraform,provider,resource…) est dans Blocs HCL (terraform-blocs-hcl). Pas un clone — focus langage de valeurs.
Ce que nous allons construire
Lab Language Basics (ca-central-1)
├── working directory = racine du root module
├── main.tf / versions.tf → syntaxe HCL native (.tf)
├── aperçu *.tf.json → variante JSON
├── lexique HCL + intro blocs
└── terraform fmt → init → validate (pas d’apply obligatoire)
(Schéma à remplacer par une image locale Excalidraw / draw.io, alt : « Terraform Language Basics : .tf, HCL, working directory et validate ».)
Étape 1 — Fichiers .tf : configuration native et manifests
Idée d’origine #1 (enrichie). Terraform attend la syntaxe native pour les fichiers au suffixe .tf. On les appelle Terraform configuration files ou manifest files : ils déclarent l’état désiré de l’infrastructure.
Concrètement :
- Tous les
*.tfdu working directory (root module) sont lus et fusionnés en une config logique. - L’ordre des fichiers n’impose pas l’ordre d’exécution : Terraform construit un graphe de dépendances.
- Conventions utiles :
versions.tf,providers.tf,main.tf,variables.tf,outputs.tf. - Un dossier = un root module (
init/plan/apply). Ne mélangez pas plusieurs racines.
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ca-central-1" # AWS_PROFILE / SSO — jamais de clés
}
Les .tf sont du HCL — cœur des Terraform Language Basics (types + expressions).
Étape 2 — Variante JSON : fichiers .tf.json
Idée d’origine #2 (enrichie). Une variante JSON du langage existe, avec l’extension .tf.json.
| Aspect | .tf (HCL) |
.tf.json |
|---|---|---|
| Usage | Humains, labs, équipes | Génération machine / pipelines |
| Commentaires | # et / … / |
Non (JSON strict) |
| Virgules | Non entre arguments | Obligatoires |
| Lisibilité | Haute | Plus verbeuse |
Terraform accepte les deux dans le même working directory et les fusionne. En lab DEH, privilégiez HCL / .tf. Gardez .tf.json quand un outil génère la config.
{
"terraform": {
"required_version": ">= 1.9.0",
"required_providers": {
"aws": {
"source": "hashicorp/aws",
"version": "~> 5.0"
}
}
},
"provider": {
"aws": [{ "region": "ca-central-1" }]
}
}
Étape 3 — Working directory : où les commandes s’exécutent
Idée d’origine #3 (enrichie). Les commandes Terraform s’exécutent dans le terraform working directory — le dossier courant d’où vous lancez init, plan, apply, fmt, validate, etc.
cddans le bon dossier avant toute commande.- Terraform charge les
.tf/.tf.jsonde ce dossier (pas les sous-dossiers sansmodule/-chdir). - Le state local (
terraform.tfstate) et.terraform/(providers) apparaissent ici. - Option :
terraform -chdir=/chemin/vers/lab plansans changer de shell.
mkdir -p ~/terraform-lang-lab
cd ~/terraform-lang-lab
# working directory = $(pwd) au moment des commandes terraform
Erreur classique : lancer plan depuis le home alors que les .tf sont ailleurs — Terraform ne voit rien (ou un autre root module).
Étape 4 — Configuration Syntax : lexique HCL
Section Configuration Syntax (vide sur la page live) : lire et écrire du HCL correct.
Identifiants
Lettres, chiffres, underscores ; snake_case recommandé (lab_lang, bucket_name). Pas d’espaces ; évitez les tirets dans les noms locaux de ressources. Sensible à la casse.
resource "aws_s3_bucket" "lab_lang" { /* ... */ }
# À éviter pour le label local : Lab-Lang, CamelCase confus
Arguments
Paire nom = valeur dans un bloc. Pas de virgule entre arguments (contrairement au JSON) : un retour à la ligne suffit. terraform fmt aligne et indente (2 espaces).
region = "ca-central-1"
enabled = true
Chaînes, commentaires, types HCL
Les strings utilisent des guillemets doubles "…". Commentaires : # (ligne), / … / (bloc), ou fin de ligne. Jamais de secrets dans les commentaires ni le HCL.
| Type | Exemple | Note pédagogique |
|---|---|---|
string |
"ca-central-1" |
Guillemets doubles ; heredoc <<EOT pour multi-lignes |
number |
3 / 1.5 |
Sans guillemets |
bool |
true / false |
Sans guillemets |
list(...) |
["a", "b"] |
Index [0] ; éléments homogènes en typage strict |
set(...) |
toset(["a","a"]) |
Unicité ; pas d’ordre stable pour l’index |
map(...) |
{ env = "lab" } |
Clés string → valeurs |
object({…}) |
{ name = string, n = number } |
Schéma nommé (souvent en variable) |
tuple([…]) |
["lab", 3, true] |
Positions typées ; rare en labs débutants |
any |
(évitez) | Désactive le contrôle de type — dernier recours |
tags = {
Project = "devopselastichayway"
ManagedBy = "terraform"
Lesson = "language-basics"
Region = "ca-central-1"
}
# Commentaire : Region de lab DEH — jamais de secret ici
region = "ca-central-1" # fin de ligne OK
Expressions : littéraux, références, interpolations
Une expression produit une valeur. Quatre familles à connaître dès maintenant :
- Littéral —
"ca-central-1",3,true,["a"],{ k = "v" } - Référence —
var.region,local.name_prefix,aws_s3_bucket.lab.id(après resource),data.aws_caller_identity.current.account_id - Interpolation — dans une string :
"projet-${var.env}"(template) - Appel de fonction —
lower("LAB"),length(var.azs),merge(local.common_tags, { Extra = "x" })
region = "ca-central-1"
# Aperçu (détail Variables / Locals) :
# region = var.aws_region
# label = "projet-${var.env}"
# tags = merge({ ManagedBy = "terraform" }, var.extra_tags)
Opérateurs utiles. Comparaison (==, !=), logique (&&, ||, !), et ternaire condition ? a : b (détail : Conditionnels).
instance_type = var.env == "prod" ? "t3.small" : "t3.micro"
name_label = lower("DEH-${var.env}-lab")
az_count = length(["ca-central-1a", "ca-central-1b"])
Fonctions courantes. lower / upper, length, merge, lookup, try, format, join / split, toset. Catalogue complet : Expressions. Boucles et dynamic blocks = tutos dédiés.
Bonne pratique. Nommez les expressions via locals plutôt qu’une interpolation géante dans chaque resource.
Étape 5 — Structure d’une config + intro Blocks
Section Blocks (vide sur la page live), sans cannibaliser le tuto Blocs.
Un bloc HCL a : (1) un type, (2) zéro à deux labels, (3) un corps { … } d’arguments (et parfois de blocs imbriqués).
# type label1 label2
resource "aws_s3_bucket" "lab_lang" {
bucket = "deh-lab-lang-SUFFIXE-UNIQUE"
tags = {
Project = "devopselastichayway"
}
}
| Type (aperçu) | Rôle en une phrase | Approfondir |
|---|---|---|
terraform |
Version moteur + providers (+ backend) | terraform-blocs-hcl |
provider |
Comment joindre le cloud (Region, auth) | Blocs + Providers |
resource |
Objet géré (créer / maj / détruire) | Blocs + Providers |
variable / output / locals |
Entrées, sorties, dérivés | Variables / Outputs / Locals |
data / module |
Lecture seule / réutilisation | Data sources / Modules |
Retenez : tout le HCL utile s’organise en blocs ; les arguments vivent dedans ; les fichiers .tf ne sont qu’un découpage lisible de la même config.
Organisation multi-fichiers (rappel)
Terraform charge l’ensemble du root module (pas fichier par fichier). Découpez pour la relecture Git ; gardez les secrets hors dépôt (AWS_PROFILE / SSO).
Étape 6 — Mini-lab : fmt et validate (sans apply)
mkdir -p ~/terraform-lang-lab && cd ~/terraform-lang-lab
Créez main.tf (contenu de l’étape 1 suffit : blocs terraform + provider). Puis :
export AWS_PROFILE=lab # adaptez ; surtout utile si apply volontaire plus tard
terraform fmt -recursive
terraform init
terraform validate
Attendus : fmt normalise l’indentation ; init télécharge le provider AWS 5.x ; validate affiche Success! The configuration is valid.
Pas d’apply obligatoire. Si vous créez quand même un bucket : nom globalement unique, tags, puis terraform destroy.
# Nettoyage soft (sans apply)
cd ~ && rm -rf ~/terraform-lang-lab
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
| Aucun fichier / config vide | Mauvais working directory | cd vers les .tf ou -chdir |
Parse error près d’une , |
Virgules style JSON dans un .tf |
Supprimez les virgules |
Invalid character |
Guillemets simples '…' |
Utilisez "…" |
Confusion .tf / .tf.json |
Doublon ou JSON invalide | Un format par intention ; JSON sans commentaires |
validate avant init |
Providers absents | terraform init d’abord |
| Clés AWS dans le HCL | Anti-pattern | Profil / AWS_PROFILE / SSO |
Récapitulatif
- Les
.tfportent la syntaxe native HCL (configuration / manifest files). - La variante
.tf.jsonsert surtout à la génération machine ; le lab privilégie HCL. - Les commandes s’exécutent dans le working directory (root module).
- Configuration Syntax : identifiants, arguments, types HCL, expressions (littéraux, refs, interpolations, fonctions).
- Intro Blocks : type + labels + corps → détail dans le tuto Blocs.
fmtpuisvalidate(aprèsinit) sans apply obligatoire.- Terraform ≥ 1.9, AWS provider 5.x, Region
ca-central-1. - Zéro secret dans les manifests.
Suite de la série
- Blocs HCL Terraform (
terraform-blocs-hcl) —terraform/provider/resource - Workflow Terraform (
terraform-workflow) — lire le plan avant tout apply - Variables Terraform (
terraform-variables) — parametrer Region, noms, tags - Aussi : Providers et ressources · Locals · Outputs
FAQ courte
Qu’est-ce qu’un fichier .tf ? Manifest HCL du working directory ; tous les *.tf du root sont fusionnés.
Quand utiliser .tf.json ? Génération machine. À la main : HCL.
Pourquoi plan ne voit rien ? Mauvais working directory : cd ou -chdir.
validate remplace-t-il plan ? Non. validate = syntaxe ; plan = delta cloud/state.
Tous les blocs dès Language Basics ? Non — types/expressions ici ; catalogue blocs dans Blocs HCL.
Pourquoi / quand revenir aux bases du langage
Types HCL, expressions et working directory expliquent 80 % des erreurs « bêtes » (mauvais dossier, mauvaise interpolation, confusion .tf / .tf.json). Parcourez cette page avant Variables et Blocs si le jargon « argument / expression / block » reste flou.
Pièges language basics
- Lancer
terraformhors du dossier contenant les.tf(ou sans-chdir). - Croire que l’ordre des fichiers impose l’ordre de création : c’est le graphe qui décide.
- Interpoler inutilement (
"${var.x}"alors quevar.xsuffit pour une string déjà string). - Générer du JSON
.tf.jsonà la main sans besoin d’outil : HCL reste plus lisible pour les humains. - Glisser des secrets dans un littéral « temporaire » : même en lab, profil AWS + TF ≥ 1.9 + Region
ca-central-1.
Quand utiliser expressions vs hardcode
Hardcode pour un lab jetable d’une ressource. Expressions (var, local, fonctions) dès que vous répétez un nom, un tag ou une Region — préparation naturelle aux tutos Variables et Locals.
FAQ étendue (language)
validate a-t-il besoin du réseau ? Souvent oui après init (schémas providers). Hors ligne stricte : providers déjà en cache.
Puis-je commenter en # et // ? Oui en HCL natif ; blocs / … / aussi. Pas de commentaires dans le JSON strict .tf.json.
Quelle est la différence entre type HCL et type Terraform variable ? Les types de variables (string, object(…)) s’appuient sur le système de types du langage ; le tuto Variables détaille contraintes et validation.
Retour parcours Terraform — hub de la série et leçons sœurs.



