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 8 / 2411 min readUpdated September 13, 2026

Variables Terraform : input types et validation

À la fin de ce tutoriel, vous saurez déclarer des variables d’entrée (variable), choisir les types (string, number, bool, list, map, object, set), ajouter default, description, sensitive, nullable et des blocs de validation, puis comprendre la priorité d’assignation (default → tfvars → -var → TF_VAR_) avec un lab S3 en Region ca-central-1 (préfixe de bucket et tags via variables).

Niveau : Débutant · Temps estimé : 35–45 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-variables · Série : Terraform · Remplace / fusionne : #1635

Prérequis

  • Avoir suivi Providers et ressources (terraform-providers-ressources) : required_providers, provider AWS, adresse TYPE.NAME
  • Avoir suivi Blocs HCL (terraform-blocs-hcl) et Workflow Terraform (terraform-workflow)
  • Terraform ≥ 1.9, AWS CLI v2, profil de lab prêt (aws sts get-caller-identity OK)

Coût estimé : 0 € si vous vous arrêtez à init / plan (recommandé). Un apply créerait un bucket S3 (Free Tier / faible coût) : destroy obligatoire. Aucun secret dans le HCL ni dans les tfvars commités.

Auth sans secrets. Utilisez AWS_PROFILE / SSO. Jamais d’access_key / secret_key dans le provider ni de mots de passe dans *.tfvars versionnés.

Ce que nous allons construire

Lab variables Terraform (ca-central-1)
  ├── versions.tf / providers.tf → aws ~> 5.0, region ca-central-1
  ├── variables.tf     → types, defaults, sensitive, validation
  ├── terraform.tfvars → valeurs lab (préfixe, tags)
  ├── main.tf          → bucket S3 paramétré via var.*
  └── init → plan (+ priorité d’assignation)

(Schéma à remplacer par une image locale Excalidraw / draw.io, alt : « Variables Terraform : déclaration, types, validation et priorité d’assignation ».)

Ce guide révise et actualise le post #1635 : variables d’entrée Terraform 1.9+, types et validation — sans rejouer providers/ressources ni anticiper locals/outputs.

Étape 1 — Pourquoi des variables ?

Sans variables, chaque environnement (lab, staging, prod) duplique le HCL : noms de buckets, tags, tailles… Une typo et les configs divergent.

Les variables d’entrée (variable) rendent le module réutilisable : le même code reçoit des valeurs différentes selon l’environnement. Vous paramétrez un préfixe de bucket, des tags ou un booléen « activer versioning » sans réécrire les resource.

Avantages : réutilisabilité, environnements distincts sans fork de code, clarté via description + validation, et sensible pour masquer les secrets dans les logs (sans remplacer un coffre-fort). Les variables ne remplacent pas les locals (dérivés) ni les outputs (expositions) — prochains tutoriels.

Étape 2 — Bloc variable : attributs essentiels

Déclarez chaque entrée dans variables.tf (convention) :

variable "bucket_prefix" {
  type        = string
  description = "Préfixe du nom de bucket S3 (minuscules, chiffres, tirets)."
  default     = "deh-lab"
  nullable    = false
  sensitive   = false

  validation {
    condition     = can(regex("^[a-z0-9][a-z0-9-]{1,20}$", var.bucket_prefix))
    error_message = "bucket_prefix doit être un préfixe S3 valide (2–21 caractères)."
  }
}
Attribut Rôle
type Contrainte (string, number, bool, list, map, object, set…)
default Valeur si rien n’est fourni ailleurs (rend la variable optionnelle)
description Documentation affichée dans le plan / l’UI
sensitive Masque la valeur dans CLI et logs (ne chiffre pas le state)
nullable Si false, refuse null même avec un default

Sans default, Terraform exige une valeur (tfvars, -var ou TF_VAR_). Référencez toujours avec var.NOM.

Étape 3 — Types courants

variable "environment" {
  type        = string
  description = "Nom d’environnement court."
  default     = "lab"
}

variable "retention_days" {
  type        = number
  default     = 7
}

variable "enable_versioning" {
  type        = bool
  default     = false
}

variable "availability_zones" {
  type        = list(string)
  default     = ["ca-central-1a", "ca-central-1b"]
}

variable "extra_tags" {
  type        = map(string)
  default = {
    Owner = "devopselastichayway"
    Stage = "variables-lab"
  }
}

variable "bucket_config" {
  type = object({
    force_destroy = bool
    purpose       = string
  })
  default = {
    force_destroy = true
    purpose       = "terraform-variables-lab"
  }
}

variable "allowed_stages" {
  type    = set(string)
  default = ["lab", "dev", "staging"]
}
  • Scalaires : string, number, bool.
  • list(T) : séquence ordonnée (var.availability_zones[0]).
  • map(T) : clés → valeurs (var.extra_tags["Owner"]).
  • object({…}) : structure nommée pour regrouper des options.
  • set(T) : sans doublons ni ordre stable.

Un mauvais type (string là où un number est attendu) échoue avant l’appel API.

Étape 4 — Blocs validation personnalisés

La condition doit être booléenne et ne référencer que la variable validée :

variable "environment" {
  type    = string
  default = "lab"

  validation {
    condition     = contains(["lab", "dev", "staging"], var.environment)
    error_message = "environment doit être lab, dev ou staging."
  }
}

variable "retention_days" {
  type    = number
  default = 7

  validation {
    condition     = var.retention_days >= 1 && var.retention_days <= 90
    error_message = "retention_days doit être entre 1 et 90."
  }
}

Si la condition est fausse, Terraform affiche error_message et s’arrête — première défense contre un préfixe S3 invalide ou un enum hors liste.

Étape 5 — Priorité d’assignation

Du plus faible au plus fort :

  1. default dans le bloc variable
  2. ***.auto.tfvars** (ordre alphabétique)
  3. terraform.tfvars / .json
  4. -var-file=… (ordre CLI)
  5. -var='name=value'
  6. TF_VAR_name (souvent en CI ; testez les conflits avec un plan)

Pratique lab : defaults sûrs dans variables.tf, valeurs d’environnement dans terraform.tfvars (ou lab.auto.tfvars), overrides ponctuels via -var / TF_VAR_.

export TF_VAR_environment=dev
terraform plan -var='bucket_prefix=deh-ci'

Étape 6 — tfvars et .gitignore des secrets

terraform.tfvars (valeurs lab, pas de secrets) :

bucket_prefix     = "deh-lab"
environment       = "lab"
enable_versioning = false

extra_tags = {
  Owner   = "devopselastichayway"
  Stage   = "variables-lab"
  Project = "devopselastichayway"
}
  • terraform.tfvars et *.auto.tfvars sont chargés automatiquement à la racine du module.
  • Secrets : jamais commités. Exemple .gitignore :
*.tfvars
!*.tfvars.example
*.tfvars.json
.terraform/

Versionnez un terraform.tfvars.example. Attention : sensitive masque l’affichage mais la valeur reste en clair dans le state — chiffrez le backend distant.

Étape 7 — Lab ca-central-1 : préfixe et tags

mkdir -p ~/terraform-variables-lab && cd ~/terraform-variables-lab
export AWS_PROFILE=lab
export AWS_REGION=ca-central-1
aws sts get-caller-identity

versions.tf — required_version = ">= 1.9.0", hashicorp/aws ~> 5.0 (comme le tuto Providers).

providers.tf — region = "ca-central-1", default_tags (Project / ManagedBy / Stage), aucune clé.

variables.tf — déclarations des étapes 2–4 (bucket_prefix, environment, enable_versioning, extra_tags, bucket_config + validations).

terraform.tfvars — valeurs de l’étape 6.

main.tf :

resource "aws_s3_bucket" "lab_variables" {
  # Remplacez SUFFIXE-UNIQUE (initiales + date)
  bucket        = "${var.bucket_prefix}-${var.environment}-SUFFIXE-UNIQUE"
  force_destroy = var.bucket_config.force_destroy

  tags = merge(
    var.extra_tags,
    {
      Name        = "${var.bucket_prefix}-${var.environment}"
      Environment = var.environment
      Purpose     = var.bucket_config.purpose
    }
  )
}

resource "aws_s3_bucket_versioning" "lab_variables" {
  bucket = aws_s3_bucket.lab_variables.id

  versioning_configuration {
    status = var.enable_versioning ? "Enabled" : "Suspended"
  }
}

resource "aws_s3_bucket_public_access_block" "lab_variables" {
  bucket = aws_s3_bucket.lab_variables.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
terraform init && terraform fmt -recursive && terraform validate && terraform plan

Attendez des + sur bucket, versioning et public access block ; vérifiez préfixe et tags dans le plan. Pas d’obligation d’apply ; si vous appliquez, enchaînez un destroy. Override : terraform plan -var='environment=dev' -var='enable_versioning=true'.

Étape 8 — Checklist

  1. variables.tf avec type + description pour chaque entrée.
  2. default sûr ou valeur obligatoire via tfvars / CI.
  3. sensitive = true pour secrets — ne pas les committer.
  4. validation pour préfixes, enums et plages.
  5. Priorité : default → auto.tfvars → terraform.tfvars → -var-file → -var / TF_VAR_.
  6. Gitignorer .tfvars secrets ; versionner .tfvars.example.
  7. Référencer var.NOM ; composer avec merge / interpolations.
  8. init → fmt → validate → plan ; destroy si apply.

Nettoyage

Sans apply : rm -rf ~/terraform-variables-lab. Avec apply : terraform destroy, vérifiez l’absence du bucket en ca-central-1, puis supprimez le dossier.

Erreurs fréquentes

Symptôme Cause Correction
Type mismatch / Invalid value string là où number/bool est attendu Alignez le type (7 vs "7", true vs "true")
Variable required au plan Pas de default ni assignation default, tfvars, -var ou TF_VAR_
Sensitive leak dans les logs Oubli de sensitive ou output dérivé non marqué Marquez variable et outputs ; n’imprimez pas var.* sensible
Validation toujours fausse Condition qui référence d’autres vars Limitez à var.NOM validée
Mauvaise valeur « gagne » Confusion de priorité terraform console → var.NOM ; une seule source claire
Secrets dans Git *.tfvars commités .gitignore + rotation
Bucket name invalide Préfixe hors règles S3 Validation regex + suffixe unique

Quiz (3 questions)

1. Où déclare-t-on le type et la description d’une entrée ?

  • A. Uniquement dans terraform.tfvars
  • B. Dans un bloc variable (souvent variables.tf)
  • C. Dans le bloc provider

2. Que fait sensitive = true ?

  • A. Chiffre la valeur dans le state distant
  • B. Masque la valeur dans le plan / la CLI (sans chiffrer le state)
  • C. Empêche toute assignation via TF_VAR_

3. Quelle source l’emporte sur un default ?

  • A. Rien — le default est toujours prioritaire
  • B. Une valeur via terraform.tfvars, -var ou TF_VAR_
  • C. Uniquement .terraform.lock.hcl

Réponses : 1‑B · 2‑B · 3‑B

Pourquoi / quand introduire des variables d’entrée

Hardcoder la Region, les préfixes S3 et les tags fonctionne pour un fichier jetable. Dès que vous rejouez le lab, changez d’environnement ou partagez le module, les input variables deviennent le contrat : types, descriptions, defaults sûrs, validations, sensitive. Ce tuto pose ce contrat avant Locals et Outputs.

Quand choisir default, tfvars ou TF_VAR_

  • default : valeur de lab inoffensive (ex. Region ca-central-1) qui permet plan sans friction.
  • terraform.tfvars / -var-file : valeurs d’environnement versionnées sans secrets (ou fichiers gitignorés pour les secrets).
  • -var / TF_VAR_ : override CI ou one-shot local.
  • Pas de default : force l’appelant à choisir (utile pour un préfixe bucket unique).

Rappel de priorité (du plus faible au plus fort) : default → fichiers auto → terraform.tfvars → -var-file → -var / env. Vérifiez avec terraform console si un doute demeure.

Pièges des variables

  • Types lâches (string partout) : préférez bool, number, object, map pour échouer tôt.
  • sensitive = true oublié sur un token… ou output dérivé non marqué qui le réaffiche.
  • Validation qui référence d’autres variables de façon non supportée : gardez la condition locale à var.NOM.
  • Commit de secrets.tfvars : .gitignore + exemple *.tfvars.example uniquement.
  • Validation regex S3 trop permissive : refusez majuscules et underscores tôt.
  • Documenter des access keys « en variable » : non — l’auth reste profil/SSO ; TF ≥ 1.9.

Pourquoi valider tôt

Une validation claire transforme une erreur AWS obscure (BucketAlreadyExists, InvalidBucketName) en message Terraform actionnable avant l’apply. C’est du temps d’incident économisé.

Patterns utiles sans HCL supplémentaire

  • Préfixe + suffixe unique (date / prénom) pour les noms globaux S3.
  • Map de tags communs fusionnée (merge) avec des tags spécifiques.
  • Booléen enable_versioning pour activer un resource optionnel (avec count/for_each dans les tutos suivants).
  • Enum d’environnements (dev/staging/prod) via validation contains.

FAQ variables (étendue)

Variable vs local ? Variable = entrée externe ; local = calcul interne non surchargé par tfvars.

Puis-je changer le type après coup ? Oui mais cela casse les appels existants : versionnez le contrat (surtout en module).

Les variables apparaissent-elles dans le state ? Les valeurs résolues influencent resources/state ; les secrets sensibles restent à traiter avec précaution (remote state chiffré, pas de printf).

Faut-il une variable pour la Region ? Souvent oui, avec default ca-central-1 pour la série ; le provider consomme var.aws_region ou équivalent.

Comment documenter pour un collègue ? description obligatoire + fichier example tfvars + README du module.

Override en CI sans fichier ? TF_VAR_environment=dev dans la pipeline, combiné à -input=false.

Objets imbriqués ? object({ … }) ou map(object) : plus strict qu’un any opaque.

Sensitive et plan JSON ? Les valeurs marquées sont rédigées dans beaucoup de sorties CLI ; ne vous y fiez pas comme à un coffre-fort.

Pour aller plus loin

  • Doc : Input Variables, Validation, Assigning Values
  • Sur ce site : Locals, puis Outputs ; révisez Blocs HCL et Providers
  • Rappel : une variable bien typée + validée évite plus d’incidents qu’un apply précipité

Maillage série Terraform (P2)

← Précédent Providers et ressources (terraform-providers-ressources)
→ Suivant Locals (terraform-locals)
Aussi Outputs (terraform-outputs) · Blocs HCL (terraform-blocs-hcl)
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

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 *