DevOps Elastic Hayway
Document

SUBSCRIBE TO GET FULL ACCESS TO THE E-BOOKS FOR FREE 🎁SUBSCRIBE NOW

Professional Dropdown with Icon

SUBSCRIBE NOW TO GET FREE ACCESS TO EBOOKS

TerraformLesson 3 / 2410 min readUpdated October 7, 2026

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 blocs terraform / provider / resource (voir terraform-blocs-hcl). Lab fmt / validate en Region ca-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çu init → 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 *.tf du 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.

  1. cd dans le bon dossier avant toute commande.
  2. Terraform charge les .tf / .tf.json de ce dossier (pas les sous-dossiers sans module / -chdir).
  3. Le state local (terraform.tfstate) et .terraform/ (providers) apparaissent ici.
  4. Option : terraform -chdir=/chemin/vers/lab plan sans 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 :

  1. Littéral — "ca-central-1", 3, true, ["a"], { k = "v" }
  2. Référence — var.region, local.name_prefix, aws_s3_bucket.lab.id (après resource), data.aws_caller_identity.current.account_id
  3. Interpolation — dans une string : "projet-${var.env}" (template)
  4. 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

  1. Les .tf portent la syntaxe native HCL (configuration / manifest files).
  2. La variante .tf.json sert surtout à la génération machine ; le lab privilégie HCL.
  3. Les commandes s’exécutent dans le working directory (root module).
  4. Configuration Syntax : identifiants, arguments, types HCL, expressions (littéraux, refs, interpolations, fonctions).
  5. Intro Blocks : type + labels + corps → détail dans le tuto Blocs.
  6. fmt puis validate (après init) sans apply obligatoire.
  7. Terraform ≥ 1.9, AWS provider 5.x, Region ca-central-1.
  8. 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 terraform hors 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 que var.x suffit 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.

Share your love

Leave a Reply

Your email address will not be published. Required fields are marked *