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 aveclocals, puis exposer le résultat en outputs — sans cloner les guides Variables ni Data sources. Regionca-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) :datavsresource, timing - Idéalement Locals (
terraform-locals) et Providers (terraform-providers-ressources) - Terraform ≥ 1.9, AWS CLI v2, profil de lab (
aws sts get-caller-identityOK)
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_amilit l’AMI officielle du compte / Region. - Un local
common_tagsinjecteAccountId(issu dedata.aws_caller_identity) +Environment(issu devar.env). - Un output
ami_idprouve 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 :
ownersetvaluesviennent de variables → rejouable / revue Git claire.most_recent = true+ filtres stricts réduisent le risque « multiple results ».aws_availability_zoneslit 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 labavailability_zonescontientca-central-1a/1b(selon le compte)ami_idcommence parami-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é
- Variables pour tout ce qui change (Region, env, filtres AMI)
- Data sources pour tout ce qui existe déjà (account, AZ, AMI)
- Locals pour dériver noms / tags (pas pour cacher des inputs)
- Outputs pour prouver la lecture avant d’ajouter des resources
- Aucun ID AMI en dur ; aucun secret dans tfvars Git
planlu avantapply; 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_identityen 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.



