Data sources Terraform AWS (guide complet)
À la fin de ce tutoriel, vous saurez distinguer data source et resource (lire vs gérer), écrire la syntaxe
data "TYPE" "NAME", interroger les data sources AWS courants (AMI, VPC / subnet, availability zones, caller identity, bucket S3 existant), combiner variables + data, comprendre le timing (lecture au refresh / plan), anticiper les erreurs « 0 results » / « multiple results », et valider le tout avec un lab en Regionca-central-1sans ressource coûteuse.Niveau : Débutant → Intermédiaire · 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-data-sources· Série : Terraform · Remplace / fusionne : #1657, #1662, #1740, #1745
Prérequis
- Avoir suivi State distant S3 (
terraform-state-backend-s3) : backend, state partagé, bonnes pratiques - Avoir suivi Providers et ressources (
terraform-providers-ressources) : adresseTYPE.NAME, provider AWS - Avoir suivi Variables (
terraform-variables) :variable,default, tfvars - Terraform ≥ 1.9, AWS CLI v2, profil de lab (
aws sts get-caller-identityOK)
Coût estimé : 0 € si vous vous limitez à init / plan / apply sur des data sources seuls (recommandé). Aucune AMI EC2, aucun VPC ni bucket coûteux à créer. Option légère : un null_resource ou un tag local — destroy si vous créez quoi que ce soit. Aucun secret dans le HCL ni les tfvars commités.
Auth sans secrets. Utilisez
AWS_PROFILE/ SSO. Jamais d’access_key/secret_keydans le provider. Les data sources lisent le compte : restreignez l’IAM (lecture seule pour ce lab).
Ce que nous allons construire
Lab data sources Terraform (ca-central-1)
├── versions.tf / providers.tf → TF ≥ 1.9, aws ~> 5.0, region ca-central-1
├── variables.tf → filtres AMI / nom VPC (optionnels)
├── data.tf → caller_identity, availability_zones, (ami)
├── outputs.tf → account_id, azs, ami_id
└── init → plan → apply (data only) → destroy (si ressource légère)
(Alt : « Data sources Terraform AWS : lire AMI, VPC, AZ et identité du compte sans gérer la ressource ».)
Ce guide fusionne et remplace les doublons #1657, #1662, #1740 et #1745 : un seul parcours P2 sur les data sources Terraform AWS, actualisé 2026 (TF ≥ 1.9, provider ~> 5.0, Region ca-central-1).
Étape 1 — Data vs resource : lire vs gérer
Une resource (resource "aws_s3_bucket" "lab") déclare un objet que Terraform crée, met à jour et détruit. Elle apparaît dans le state comme gérée : apply peut la modifier.
Une data source (data "aws_caller_identity" "current") interroge une API ou un objet déjà existant. Terraform ne le crée pas, ne le détruit pas : il lit des attributs (ID, ARN, liste d’AZ…) pour les réutiliser dans d’autres blocs.
| Aspect | resource |
data |
|---|---|---|
| Rôle | Gérer le cycle de vie | Lire l’existant |
| State | Suivi (create / update / destroy) | Snapshot des attributs lus |
destroy |
Supprime l’objet cloud | Retire seulement la lecture du state |
| Cas typique | Nouveau bucket, SG, instance | AMI officielle, VPC par défaut, account ID |
En pratique : resource pour ce que ce stack possède ; data pour l’existant du compte (AMI Amazon Linux, subnets d’un VPC partagé, AZ).
Étape 2 — Syntaxe data "TYPE" "NAME"
Le type suit le provider (aws_…). Le nom local est libre ; l’adresse est data.TYPE.NAME.
# data.tf — forme générale
data "aws_caller_identity" "current" {}
data "aws_availability_zones" "available" {
state = "available"
}
# Référence ailleurs :
# data.aws_caller_identity.current.account_id
# data.aws_availability_zones.available.names
Arguments du bloc = filtres de requête. Les attributs exportés (registry AWS provider) se consomment via data.<type>.<name>.<attr> dans resources, locals ou outputs.
Étape 3 — Cas AWS courants (AMI, VPC, AZ, identity, S3)
Data sources typiques dès le premier projet AWS :
| Data source | Usage | Filtre / argument clé |
|---|---|---|
aws_caller_identity |
Account ID, ARN, user ID | Aucun (compte du provider) |
aws_availability_zones |
Liste des AZ de la region | state = "available" |
aws_ami |
AMI la plus récente (filtre owners + name) | most_recent, filter, owners |
aws_vpc / aws_subnet / aws_subnets |
VPC ou subnets existants | default, tags, filter |
aws_s3_bucket |
Métadonnées d’un bucket déjà créé | bucket = "nom-existant" |
Exemple AMI Amazon Linux 2023 (lecture seule — ne lance pas d’instance) :
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "state"
values = ["available"]
}
}
VPC / subnet : data "aws_vpc" "default" { default = true } ou filtres tags ; aws_subnets pour une liste d’IDs. Bucket existant : data "aws_s3_bucket" "logs" { bucket = var.existing_log_bucket } pour brancher logging / politiques sans recréer le bucket.
Étape 4 — Combiner variables + data (exemple concret)
Les variables paramétrent la recherche ; les data résolvent l’ID au plan.
# variables.tf
variable "ami_name_pattern" {
type = string
description = "Motif du nom d’AMI Amazon Linux (filtre name)."
default = "al2023-ami-*-x86_64"
}
variable "ami_owners" {
type = list(string)
description = "Owners AMI (amazon = comptes officiels)."
default = ["amazon"]
}
# data.tf
data "aws_ami" "selected" {
most_recent = true
owners = var.ami_owners
filter {
name = "name"
values = [var.ami_name_pattern]
}
}
# outputs.tf
output "resolved_ami_id" {
description = "AMI résolue via data + variables."
value = data.aws_ami.selected.id
}
Même pattern pour un VPC tagué Environment = var.env ou var.log_bucket_name : critères stables, pas d’ID en dur.
Étape 5 — Timing : lecture au refresh / plan
Les data sont évaluées au refresh (implicite dans plan / apply, sauf -refresh=false) :
terraform planappelle déjà les APIs (STS, Describe*, Head…) — credentials + droits lecture requis.- Si l’existant change (nouvelle AMI
most_recent, AZ ajoutée), le plan peut proposer des remplacements en aval. - Les data ne créent rien : apply « data only » = snapshot dans le state, sans facture EC2 / RDS.
Astuce : plan -refresh=false après un refresh réussi (hors ligne) — rare en CI.
Étape 6 — Erreurs : 0 results et multiple results
Deux messages classiques avec aws_ami, aws_vpc, aws_subnet, etc. :
| Symptôme | Cause | Correction |
|---|---|---|
Your query returned no results |
Filtres trop stricts, mauvaise region, owner incorrect | Assouplir filter, vérifier ca-central-1, owners |
Your query returned more than one result / besoin d’un seul objet |
Plusieurs VPC / AMI matchent sans most_recent ni ID unique |
Ajouter most_recent = true, tags plus précis, ou id exact |
| Accès refusé STS / Describe* | IAM trop restreint ou mauvais profil | AWS_PROFILE, politique lecture |
Bucket introuvable (aws_s3_bucket) |
Nom faux ou autre compte / region | Vérifier nom + region du provider |
Règle : data « un objet » → filtres uniques ou most_recent ; listes (aws_availability_zones, aws_subnets) → names / ids.
Étape 7 — Lab ca-central-1 (identity + AZ, AMI optionnelle)
Lire le compte et les AZ sans ressource coûteuse.
# versions.tf
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# providers.tf
provider "aws" {
region = "ca-central-1"
# Auth : AWS_PROFILE / SSO — jamais de clés ici
}
# data.tf
data "aws_caller_identity" "current" {}
data "aws_availability_zones" "available" {
state = "available"
}
# Optionnel — lecture AMI seulement
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
# outputs.tf
output "account_id" {
value = data.aws_caller_identity.current.account_id
}
output "availability_zones" {
value = data.aws_availability_zones.available.names
}
output "ami_id" {
value = data.aws_ami.amazon_linux_2023.id
description = "Optionnel : retirer le bloc data ami si non désiré."
}
Commandes :
mkdir -p ~/terraform-data-sources-lab && cd ~/terraform-data-sources-lab
# collez les fichiers ci-dessus
export AWS_PROFILE=lab
export AWS_REGION=ca-central-1
terraform init
terraform plan
terraform apply -auto-approve # data only : met à jour le state, 0 €
terraform output
Vous voyez l’account ID, les AZ ca-central-1a / 1b…, et éventuellement un ami-…. Aucune EC2. Ressource légère ajoutée ? → terraform destroy -auto-approve.
Étape 8 — Checklist
- Data = lire ; resource = gérer.
data "TYPE" "NAME"→data.TYPE.NAME.attr.- Cas AWS : identity, AZ, AMI, VPC/subnet, S3 existant.
- Variables = filtres ; data = IDs résolus.
- Lecture au refresh/plan — IAM lecture.
- Anticiper 0 / multiple results.
- Lab
ca-central-1sans charge coûteuse. - Aucun secret ; profil SSO.
Nettoyage
cd ~/terraform-data-sources-lab
terraform destroy -auto-approve # no-op si data only
rm -rf ~/terraform-data-sources-lab
Rien à supprimer côté AWS sans resource créée.
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
no results sur AMI |
Motif name / owner / arch |
Ajuster filter ; tester aws ec2 describe-images |
multiple results |
Trop large sans most_recent |
most_recent = true + filters |
| Mauvaise region | Provider ≠ ca-central-1 |
Aligner provider et AWS_REGION |
| Confusion data / resource | Destroy attendu sur un data | Retirer le bloc data ; cloud intact |
Quiz (3 questions)
1. Quelle est la différence essentielle entre resource et data ?
- A.
dataest plus rapide à appliquer - B.
resourcegère le cycle de vie ;datalit l’existant - C.
datane peut pas être référencé dans un output
2. Quand Terraform lit-il typiquement une data source ?
- A. Uniquement au
destroy - B. Au refresh / plan (et apply)
- C. Seulement si vous lancez
terraform console
3. Comment éviter « Your query returned no results » sur aws_ami ?
- A. Passer
create = truesur la data - B. Vérifier region,
ownerset assouplir lesfilter - C. Remplacer la data par un
null_resource
Réponses : 1‑B · 2‑B · 3‑B
Pourquoi / quand utiliser des data sources
Une data source lit une information déjà présente chez le cloud (AMI récente, VPC par défaut, AZ, identité IAM) sans la gérer comme resource. Idéal pour éviter les IDs en dur et pour coller à l’existant (AMI Amazon Linux filtrée en ca-central-1).
Data vs resource — critères simples
- Vous créez / détruisez l’objet avec ce root →
resource. - Vous consommez un objet géré ailleurs (ou par AWS) →
data. - Vous avez besoin d’un ID au plan pour dimensionner une resource → souvent
data(+ variables).
Pièges data sources
- Filtres AMI trop larges → « multiple results » ; trop étroits → zéro résultat.
- Supposer que la data est figée : un refresh/plan peut résoudre une nouvelle AMI (effet de bord sur replace d’instances).
- Utiliser une data pour masquer un secret : le plan et le state peuvent quand même exposer des valeurs — restez clean (pas de secrets dans le HCL).
- Oublier que certaines datas exigent le réseau et des droits IAM (
ec2:Describe*,sts:GetCallerIdentity).
Quand préférer une variable
Si la valeur est un choix d’équipe (ID de VPC projet) stable et non « dernière AMI », une variable typée + tfvars est plus prévisible qu’un filtre dynamique.
FAQ data sources
La data apparaît-elle dans destroy ? Non comme resource gérée : destroy ne « supprime » pas l’AMI ou le VPC lus.
Puis-je enchaîner data → resource → output ? Oui : pattern classique du lab identity + AZ (+ AMI optionnelle).
Erreur 0 results : démarche ? Assouplir filtres, vérifier Region ca-central-1, droits IAM, nom de filtre.
TF ≥ 1.9 ? Oui ; provider AWS ~> 5.0 comme le reste de la série.
Pour aller plus loin
- Doc : Data Sources, aws_ami, aws_caller_identity, aws_availability_zones
- Sur ce site : State S3, Boucles for_each ; aussi Providers, Variables
- Suite : itérer
data.aws_availability_zones.available.namesavecfor_each
Maillage série Terraform (P2)
| ← Précédent | State S3 (terraform-state-backend-s3) |
| → Suivant | Boucles for_each (terraform-boucles-for-each) |
| Aussi | Providers (terraform-providers-ressources) · Variables (terraform-variables) |
| 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 |
Cas réel — data AMI qui « saute » de version
data.aws_ami sans filtre assez strict renvoie une nouvelle image un mardi matin : le plan propose de remplacer l’instance. En lab c’est pédagogique ; en prod c’est une outage. Pinnez owners + name regex + most_recent de façon consciente, ou passez l’AMI en variable.
Piège : une data qui référence une ressource du même module de façon circulaire. Séparez « ce qui existe déjà » (data) et « ce que ce root crée ». Les data IAM policy AWS managed sont stables ; les data d’AMI et de snapshots le sont moins.
À retenir : une data n’est pas gratuite en déterminisme. Lisez le plan quand une data change, pas seulement quand une resource change.
Retour parcours Terraform — hub de la série et leçons sœurs.



