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 11 / 246 min readUpdated September 13, 2026

Terraform : exemple variables + data sources AWS

À la fin de ce tutoriel, vous construirez un lab combiné : déclarer des variables (préfixe, environnement, filtres), lire le compte AWS via des data sources (aws_caller_identity, aws_availability_zones, aws_ami), dériver un nom et des tags avec locals, puis exposer le résultat en outputs — sans cloner les guides Variables ni Data sources. Region ca-central-1, Terraform ≥ 1.9, AWS provider ~> 5.0.

Niveau : Débutant → Intermédiaire · Temps estimé : 40–50 min · Versions testées : Terraform 1.16.2 (série ≥ 1.9), AWS provider ~> 5.0 · Dernière vérification : 2026-09-13

Slug proposé : terraform-variable-and-datasource-example · Série : Terraform · Remplace / densifie : stub EN live (exemple variables + data)

Prérequis

  • Variables Terraform (terraform-variables) : variable, types, tfvars, priorité
  • Data sources Terraform (terraform-data-sources) : data vs resource, timing
  • Idéalement Locals (terraform-locals) et Providers (terraform-providers-ressources)
  • Terraform ≥ 1.9, AWS CLI v2, profil de lab (aws sts get-caller-identity OK)

Coût estimé : 0 € en restant sur data sources + outputs (recommandé). Aucune EC2, aucun ALB. Si vous ajoutez un tag S3 optionnel : destroy obligatoire. Aucun secret dans le HCL / tfvars commités.

Différenciation. Ce n’est pas un second cours Variables ni un second Data sources : c’est un exemple intégré (pattern lab) — variables paramètrent les filtres data ; locals assemblent ; outputs prouvent la lecture. Auth : AWS_PROFILE / SSO uniquement.

Ce que nous allons construire

Lab combiné variables + data sources (ca-central-1)
  ├── versions.tf / providers.tf → TF ≥ 1.9, aws ~> 5.0, region ca-central-1
  ├── variables.tf + terraform.tfvars → env, name_prefix, ami_owners/name filter
  ├── data.tf → caller_identity, availability_zones, aws_ami (Amazon Linux 2023)
  ├── locals.tf → name_prefix dérivé, common_tags (AccountId + Env)
  ├── outputs.tf → account_id, azs, ami_id, name_prefix
  └── init → plan → apply (data only) → outputs

(Schéma à remplacer par une image locale, alt : « Exemple Terraform : variables paramètrent data sources AMI / AZ / account — ca-central-1 ».)

Objectif pédagogique : enchaîner input → lecture cloud → dérivation → sortie dans un seul root module compréhensible.

Étape 1 — Pourquoi un lab combiné ?

Les documentations séparent souvent « variables » et « data sources » pour clarifier la syntaxe. Sur le terrain, un module utile les enchaîne dès la première resource : vous paramétrez un filtre, vous lisez le cloud, vous dérivez un nom, vous exposez un output de preuve. Ce lab reproduira exactement ce geste sans créer d’EC2 facturée.

Cas réel : une équipe copie ami-0abc123 depuis la console us-east-1 dans un tfvars ca-central-1. Le apply échoue ou, pire, lance une AMI inattendue. En passant le filtre en variable et la résolution en data.aws_ami, le même code reste portable entre Regions et dans le temps (Amazon Linux 2023 évolue).

Piège : traiter ce tuto comme un second cours sur les types de variables. Ici l’objectif est le pattern intégré ; le détail des validations complexes reste dans terraform-variables, et le timing data vs resource dans terraform-data-sources.

Les tutos Variables et Data sources enseignent chacun un concept. En prod (et en certification), vous les combinez dès le premier module utile :

  • Une variable ami_name_filter évite de durcir le filtre AMI dans le HCL.
  • Une data source aws_ami lit l’AMI officielle du compte / Region.
  • Un local common_tags injecte AccountId (issu de data.aws_caller_identity) + Environment (issu de var.env).
  • Un output ami_id prouve que la lecture a réussi sans lancer d’instance.

Ce pattern évite les IDs magiques (ami-0abc…) copiés depuis la console — fragiles entre Regions et dans le temps.

Étape 2 — Provider et garde-fous

Mettre aws_region en variable (default ca-central-1) force une bonne hygiène : le provider ne contient aucune credential, et un reviewer voit immédiatement la Region dans le tfvars. En CI, vous injecterez TF_VAR_aws_region ou un -var par environnement sans forker le dépôt.

# versions.tf
terraform {
  required_version = ">= 1.9.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# providers.tf
provider "aws" {
  region = var.aws_region
  # Auth : AWS_PROFILE / SSO — jamais access_key / secret_key ici
}

La Region elle-même est une variable (default ca-central-1) : le même lab peut être rejoué ailleurs sans éditer le provider à la main.

Étape 3 — Variables d’entrée (paramètres du lab)

Les validation blocks ne sont pas du cosmétique : elles échouent avant d’appeler AWS si quelqu’un passe env = "prd" ou un préfixe avec majuscules. Pour un lab partagé, c’est moins de tickets « ça marche chez moi ». Gardez les messages d’erreur actionnables (quoi corriger), pas seulement « invalid ».

Le tfvars du lab ne doit contenir aucun secret : pas de token, pas de mot de passe RDS, pas de clé privée. Les filtres AMI et l’environnement sont des métadonnées publiques du design.

# variables.tf
variable "aws_region" {
  type        = string
  description = "Region AWS du lab."
  default     = "ca-central-1"

  validation {
    condition     = can(regex("^[a-z]{2}-[a-z]+-\d+$", var.aws_region))
    error_message = "aws_region doit ressembler à ca-central-1."
  }
}

variable "env" {
  type        = string
  description = "Environnement logique (lab, staging…)."
  default     = "lab"

  validation {
    condition     = contains(["lab", "dev", "staging"], var.env)
    error_message = "env autorisé : lab, dev, staging."
  }
}

variable "name_prefix" {
  type        = string
  description = "Préfixe court pour nommage (minuscules, tirets)."
  default     = "deh-combo"

  validation {
    condition     = can(regex("^[a-z0-9-]+$", var.name_prefix))
    error_message = "name_prefix : minuscules, chiffres, tirets uniquement."
  }
}

variable "ami_name_filter" {
  type        = string
  description = "Filtre name pour aws_ami (Amazon Linux 2023)."
  default     = "al2023-ami-*-x86_64"
}

variable "ami_owners" {
  type        = list(string)
  description = "Owners AMI (Amazon officiel = 137112412989)."
  default     = ["137112412989"]
}
# terraform.tfvars (lab — ne pas y mettre de secrets)
aws_region      = "ca-central-1"
env             = "lab"
name_prefix     = "deh-combo"
ami_name_filter = "al2023-ami-*-x86_64"

Rappel priorité (détail dans le tuto Variables) : default → terraform.tfvars → *.auto.tfvars → -var / TF_VAR_. Ici le tfvars fige le lab sans toucher au HCL.

Étape 4 — Data sources paramétrées

aws_caller_identity ancre les tags sur le vrai AccountId : utile pour éviter de coller un compte de prod dans un lab. aws_availability_zones lit les AZ de la Region du provider — si vous changez var.aws_region, les noms d’AZ suivent au prochain plan.

Pour aws_ami, multipliez les filtres (architecture, root-device, virtualization) plutôt que d’élargir le name filter au point d’obtenir plusieurs candidats. most_recent = true sans filtres stricts peut sélectionner une AMI inattendue un jour de publication Amazon.

# data.tf
data "aws_caller_identity" "current" {}

data "aws_availability_zones" "available" {
  state = "available"
}

data "aws_ami" "al2023" {
  most_recent = true
  owners      = var.ami_owners

  filter {
    name   = "name"
    values = [var.ami_name_filter]
  }

  filter {
    name   = "architecture"
    values = ["x86_64"]
  }

  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

Points clés du combo :

  • owners et values viennent de variables → rejouable / revue Git claire.
  • most_recent = true + filtres stricts réduisent le risque « multiple results ».
  • aws_availability_zones lit les AZ de la Region du provider (var.aws_region).
  • Aucune resource EC2 : on lit l’AMI, on ne la lance pas.

Si plan échoue avec « Your query returned no results », élargissez ou corrigez ami_name_filter (le nom AL2023 évolue) — ne codez pas un ami-… en dur.

Étape 5 — Locals : assembler variables + data

Le local common_tags illustre la frontière : Environment vient de l’entrée utilisateur, AccountId du cloud. Si vous mettiez tout en variables, l’opérateur devrait resaisir l’AccountId à la main (erreur garantie). Si vous mettiez tout en dur dans chaque resource, la duplication reviendrait. Les locals sont le joint entre les deux mondes — détail approfondi dans terraform-locals.

# locals.tf
locals {
  name_prefix = "${var.name_prefix}-${var.env}"

  common_tags = {
    Project     = "devopselastichayway"
    ManagedBy   = "terraform"
    Environment = var.env
    AccountId   = data.aws_caller_identity.current.account_id
    Lesson      = "variable-and-datasource-example"
  }

  # Exemple d’expression : première AZ disponible
  primary_az = data.aws_availability_zones.available.names[0]
}

Ici le local n’est pas une entrée utilisateur : il dérive un préfixe stable et des tags qui mélangent var. et data.. C’est exactement le geste manquant quand on étudie les deux concepts séparément.

Étape 6 — Outputs de preuve (sans resource coûteuse)

Des outputs clairs transforment le lab en contrat : un pipeline peut assert que ami_id commence par ami- et que name_prefix matche la convention. Vous validez le pattern avant d’ajouter aws_instance ou un ASG. C’est aussi plus sûr en démo : zéro risque d’oublier une EC2 allumée.

# outputs.tf
output "account_id" {
  description = "ID du compte AWS lu via data source."
  value       = data.aws_caller_identity.current.account_id
}

output "availability_zones" {
  description = "AZ disponibles dans la Region du provider."
  value       = data.aws_availability_zones.available.names
}

output "ami_id" {
  description = "AMI Amazon Linux 2023 résolue (filtre variables)."
  value       = data.aws_ami.al2023.id
}

output "name_prefix" {
  description = "Préfixe dérivé (variables → local)."
  value       = local.name_prefix
}

output "primary_az" {
  description = "Première AZ (expression locale)."
  value       = local.primary_az
}

output "common_tags" {
  description = "Tags assemblés (var + data)."
  value       = local.common_tags
}

Pas besoin d’EC2 pour valider le pattern : terraform apply matérialise les lectures data dans le state et affiche les outputs.

Étape 7 — Lab guidé ca-central-1

Lisez le plan attentivement : vous devez voir des data sources lues, pas de création d’instance, d’ALB ou de NAT. Si un module enfant glisse une resource coûteuse, arrêtez-vous. Après terraform output, comparez account_id avec aws sts get-caller-identity pour confirmer le profil lab.

mkdir -p ~/terraform-combo-lab && cd ~/terraform-combo-lab
# Copiez versions.tf providers.tf variables.tf terraform.tfvars data.tf locals.tf outputs.tf
export AWS_PROFILE=lab   # adaptez
terraform fmt -recursive
terraform init
terraform validate
terraform plan
terraform apply   # data only — lire le plan : 0 to add resources coûteuses
terraform output

Attendus typiques :

  • account_id = 12 chiffres de votre compte lab
  • availability_zones contient ca-central-1a / 1b (selon le compte)
  • ami_id commence par ami-
  • name_prefix = deh-combo-lab (si defaults tfvars)
terraform destroy   # retire les data du state (rien de facturé)
cd ~ && rm -rf ~/terraform-combo-lab

Option avancée (hors scope coût zéro). Brancher ami_id + primary_az dans une aws_instance t3.micro : seulement si vous acceptez le coût minute + destroy immédiat. Ce tuto reste volontairement data-only.

Étape 8 — Checklist du pattern combiné

  1. Variables pour tout ce qui change (Region, env, filtres AMI)
  2. Data sources pour tout ce qui existe déjà (account, AZ, AMI)
  3. Locals pour dériver noms / tags (pas pour cacher des inputs)
  4. Outputs pour prouver la lecture avant d’ajouter des resources
  5. Aucun ID AMI en dur ; aucun secret dans tfvars Git
  6. plan lu avant apply ; destroy / nettoyage du dossier lab

Erreurs fréquentes

Symptôme Cause Correction
no results sur aws_ami Filtre trop strict / Region Ajuster ami_name_filter ; vérifier Region
multiple results Filtres insuffisants Ajouter architecture / owner / most_recent
AccountId null dans tags Référence data avant apply Normal au premier plan partiel ; apply data
Confusion avec tuto Variables Attente d’un cours types Ici = exemple intégré, pas le cours types
Access keys dans provider Anti-pattern AWS_PROFILE / SSO uniquement
ami_owners incorrect Owner marketplace vs Amazon Utiliser l’owner Amazon documenté ou le compte partagé prévu
Plan Region inattendue AWS_REGION / provider vs var.aws_region Aligner tfvars, env shell et provider
Tags AccountId trompeurs Mauvais profil AWS Vérifier AWS_PROFILE avant apply

Quiz (3 questions)

1. Pourquoi passer ami_name_filter en variable plutôt qu’en dur dans data.aws_ami ?

  • A. Parce que Terraform l’exige
  • B. Pour rejouer / faire évoluer le filtre sans éditer la data source
  • C. Pour créer automatiquement une EC2

2. Quel rôle joue local.common_tags dans ce lab ?

  • A. Remplacer le backend S3
  • B. Assembler var.env + data.aws_caller_identity en tags réutilisables
  • C. Supprimer le besoin d’outputs

3. Ce lab crée-t-il une instance EC2 par défaut ?

  • A. Oui, obligatoire
  • B. Non — data sources + outputs seulement (EC2 = option hors scope)
  • C. Oui, mais uniquement en us-east-1

4. Quelle data source fournit l’AccountId pour les tags ?

  • A. aws_ami
  • B. aws_caller_identity
  • C. aws_lb

5. Que faire si aws_ami renvoie « no results » en ca-central-1 ?

  • A. Hardcoder une AMI us-east-1
  • B. Ajuster le filtre / owners, garder data source
  • C. Désactiver le provider AWS

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

FAQ

Pourquoi ne pas hardcoder l’AMI « stable » du mois ? Une AMI figée vieillit (patches). Un filtre + most_recent sous contrôle (owners, architecture) reste reproductible et à jour. Pinnez une AMI seulement si la conformité l’exige, via variable clairement nommée.

Ce lab remplace-t-il le tuto Variables ? Non. Il montre l’intégration. Apprenez les types et la priorité des tfvars dans terraform-variables, puis revenez ici pour le combo.

Puis-je ajouter une EC2 « pour voir » ? Oui hors scope coût zéro : acceptez la facturation minute et le destroy immédiat. Le pattern pédagogique reste data-only.

Pour aller plus loin

  • Doc : Input Variables, Data Sources, aws_ami
  • Sur ce site : Variables, Data sources, Locals, Providers, puis EC2 / ASG quand vous branchez ami_id
  • Rappel budget : lire une AMI est gratuit ; lancer l’instance ne l’est pas — destroy fait partie du métier

Maillage série Terraform (P2)

← Précédent Data sources (terraform-data-sources)
→ Suivant Locals (terraform-locals) / Loops
Aussi Variables (terraform-variables) · Providers · Conditionnels
Carte Overview · Install · Workflow · Blocks · Language basics · Providers · Variables · Exemple var+data · Locals · Outputs · State · Data sources · Loops · Conditionals · Dynamic blocks · Modules · Workspaces · Provisioners · EBS · ELB/ALB · IAM · RDS · VPC · Auto Scaling

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 *