infra / terraform
Data sources : lire l'existant
Explication
Ce que vous allez apprendre
- Distinguer une
resource(qui crée) d'unedata source(qui lit) - Récupérer dynamiquement la dernière AMI Ubuntu disponible sans coder un ID en dur
- Référencer une infrastructure partagée gérée par une autre équipe
- Lire des informations sur le compte ou la session cloud active
- Reconnaître les cas d'usage typiques où une data source est préférable à une valeur codée en dur
Dans quel contexte ?
La configuration Terraform de l'équipe utilise depuis plusieurs leçons l'ID d'AMI codé en dur ami-0c55b159cbfafe1f0. Ce problème, déjà signalé, devient concret le jour où cette AMI est dépréciée par AWS et où le prochain apply échoue avec une erreur "AMI not found" — alors que rien n'a changé dans le code lui-même.
D'abord, il faut comprendre la distinction fondamentale entre resource et data
Une resource dit à Terraform "crée et gère cet objet, du début à la fin de son cycle de vie". Une data source, elle, dit l'inverse : "va LIRE cet objet qui existe déjà, mais ne le gère pas, ne le modifie jamais et ne le détruit jamais".
Cette distinction est essentielle : un terraform destroy ne touchera JAMAIS à une ressource référencée uniquement via une data source, même si cette ressource est mentionnée explicitement dans le fichier de configuration.
resource | data | |
|---|---|---|
| Action de Terraform | Crée, modifie, détruit | Lit seulement |
Impact d'un destroy | Supprime l'objet | Aucun impact |
| Cas d'usage typique | Un bucket S3, une instance EC2 propre au projet | Une AMI officielle, un VPC partagé, l'identité du compte actif |
Prérequis
Cette leçon suppose que tu es à l'aise avec la syntaxe des blocs resource et les références entre ressources (type.nom.attribut), vues dans une leçon précédente — les data sources se référencent de façon très similaire.
Une fois cette distinction comprise, résolvons le problème de l'AMI codée en dur
data "aws_ami" "ubuntu_dernier" avec most_recent = true et un filtre sur le nom d'image demande à AWS "quelle est la dernière AMI Ubuntu 22.04 disponible, à l'instant présent ?". Le résultat s'utilise ensuite exactement comme un attribut de ressource classique, via data.aws_ami.ubuntu_dernier.id.
Il reste un autre cas d'usage très fréquent en entreprise : référencer une infrastructure gérée ailleurs
Souvent, le réseau (VPC, sous-réseaux) est géré par une équipe infrastructure séparée, dans un projet Terraform différent. Plutôt que de dupliquer cette configuration réseau, une équipe applicative peut simplement LIRE ce VPC existant via data "aws_vpc", en le filtrant par un tag connu.
Astuce
data.aws_caller_identity.courant (compte AWS actif) et data.aws_region.courant (région active) permettent d'écrire une configuration qui s'adapte automatiquement selon l'environnement dans lequel elle s'exécute, sans jamais coder ces valeurs en dur — utile notamment pour construire des ARN dynamiquement.
Le piège à connaître avant de continuer
Piège fréquent
Une data source échoue si AUCUN résultat ne correspond aux filtres fournis, ou si PLUSIEURS résultats correspondent alors qu'un seul est attendu. Vérifie toujours que tes filtres sont suffisamment précis (comme la combinaison name + virtualization-type de cette leçon) pour cibler exactement un seul objet.
Maintenant que tu sais lire l'existant, la prochaine leçon aborde le passage à l'échelle : comment regrouper des ressources en modules réutilisables, plutôt que de tout répéter dans un seul fichier plat.
Commandes & code
Data sources : lire l'existant
# Une "resource" CRÉE quelque chose ; une "data source" LIT quelque chose qui existe déjà
data "aws_ami" "ubuntu_dernier" {
most_recent = true
owners = ["099720109477"] # Canonical (éditeur d'Ubuntu)
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu_dernier.id # utilise l'AMI trouvée dynamiquement
instance_type = "t3.micro"
}
# Lire un VPC existant créé manuellement ou par une autre équipe
data "aws_vpc" "principal" {
filter {
name = "tag:Name"
values = ["vpc-production"]
}
}
data "aws_subnets" "prives" {
filter {
name = "vpc-id"
values = [data.aws_vpc.principal.id]
}
tags = {
Tier = "private"
}
}
resource "aws_instance" "app" {
ami = data.aws_ami.ubuntu_dernier.id
instance_type = "t3.micro"
subnet_id = data.aws_subnets.prives.ids[0] # premier sous-réseau privé trouvé
}
# Lire des informations sur le compte/la session AWS courante
data "aws_caller_identity" "courant" {}
output "compte_aws" {
value = data.aws_caller_identity.courant.account_id
}# Cas d'usage typiques des data sources :
# - Récupérer la dernière AMI officielle sans en coder l'ID en dur (qui change à chaque release)
# - Référencer une infra partagée (VPC, zone DNS) gérée dans un AUTRE state Terraform
# - Adapter dynamiquement la config selon le compte/la région active (data.aws_caller_identity, data.aws_region)Résumé
- Les data sources lisent des ressources existantes sans les gérer (pas de création/destruction par Terraform).
- Elles évitent de coder en dur des IDs qui changent (AMI, AZ disponibles) ou de dupliquer une infra déjà créée ailleurs.
filtercombine plusieurs critères pour cibler précisément la ressource à lire.
Exercices pratiques
Mission : fiabiliser une AMI qui vient de disparaître
Objectif : Remplacer une valeur codée en dur par une lecture dynamique, et raisonner sur ce qu'une data source protège vraiment.
Contexte
Une équipe ajoute par précipitation un data "aws_ami" "ubuntu_dernier" avec seulement owners = ["099720109477"], sans filtre name précis. terraform plan échoue avec une erreur indiquant que plusieurs résultats correspondent aux critères. Par ailleurs, un data "aws_vpc" "principal" est référencé dans plusieurs ressources applicatives du même projet.