Les meta-arguments modifient le comportement des blocs resource et module. Ils sont fournis par Terraform lui-même (pas par le provider).
count — créer N copies d’une ressource
resource "TYPE" "NOM" {
count = NUMBER
# Accès à l'index de la copie courante : count.index (commence à 0)
}# Créer 3 instances identiques
resource "aws_instance" "web" {
count = 3
ami = var.ami
instance_type = "t3.micro"
tags = {
Name = "web-${count.index}" # web-0, web-1, web-2
}
}
# Références aux instances créées :
# aws_instance.web[0].id
# aws_instance.web[1].public_ip
# aws_instance.web[*].id ← tous les IDs (splat)
# count conditionnel (créer ou ne pas créer)
resource "aws_cloudwatch_alarm" "cpu" {
count = var.env == "prod" ? 1 : 0 # créé uniquement en prod
alarm_name = "high-cpu"
...
}Limites de count :
- Le nombre doit être connu avant l’apply (pas de valeur dynamique issue d’une autre ressource)
- Si on retire un élément du milieu, Terraform renumérote et recrée tout → préférer
for_each
for_each — créer une ressource par élément d’une collection
resource "TYPE" "NOM" {
for_each = MAP_OU_SET
# Accès à la clé : each.key
# Accès à la valeur : each.value
}# for_each avec un set de strings
resource "aws_s3_bucket" "env" {
for_each = toset(["dev", "staging", "prod"])
bucket = "mon-bucket-${each.key}"
}
# Crée : aws_s3_bucket.env["dev"], aws_s3_bucket.env["staging"], aws_s3_bucket.env["prod"]
# for_each avec un map d'objets
locals {
servers = {
web = { instance_type = "t3.micro", ami = "ami-abc" }
api = { instance_type = "t3.small", ami = "ami-def" }
db = { instance_type = "t3.medium", ami = "ami-ghi" }
}
}
resource "aws_instance" "servers" {
for_each = local.servers
instance_type = each.value.instance_type
ami = each.value.ami
tags = {
Name = each.key # "web", "api", "db"
}
}
# Références :
# aws_instance.servers["web"].id
# aws_instance.servers["api"].public_ip
# for_each avec une liste de maps
resource "aws_security_group_rule" "rules" {
for_each = { for rule in var.ingress_rules : rule.port => rule }
type = "ingress"
from_port = each.value.port
to_port = each.value.port
protocol = each.value.protocol
cidr_blocks = each.value.cidr_blocks
}count vs for_each :
count | for_each | |
|---|---|---|
| Identifiant | index numérique (0, 1, 2…) | clé string |
| Suppression d’un élément | Renumérote → recrée les suivants ⚠️ | Supprime seulement l’élément ciblé ✅ |
| Cas d’usage | N copies identiques | Ressources différentes par configuration |
depends_on — forcer une dépendance explicite
Terraform calcule automatiquement les dépendances via les références. depends_on sert pour les dépendances implicites non visibles dans le code.
resource "TYPE" "NOM" {
depends_on = [RESSOURCE_1, RESSOURCE_2, MODULE]
}# Terraform ne peut pas déduire que l'instance a besoin de l'IAM role
resource "aws_instance" "app" {
ami = var.ami
instance_type = "t3.micro"
# L'instance a besoin que le role IAM soit créé AVANT
# mais aucune référence directe n'existe dans les attributs
depends_on = [aws_iam_role_policy.app_policy]
}
# Forcer l'ordre entre modules
module "database" {
source = "./modules/database"
}
module "application" {
source = "./modules/application"
depends_on = [module.database] # l'app démarre APRÈS la BDD
}provider — spécifier un provider aliasé
resource "TYPE" "NOM" {
provider = PROVIDER.ALIAS
}# Configuration de deux providers AWS
provider "aws" {
alias = "primary"
region = "eu-west-1"
}
provider "aws" {
alias = "backup"
region = "us-east-1"
}
# Ressource dans la région primaire
resource "aws_s3_bucket" "primary" {
provider = aws.primary
bucket = "mon-bucket-primary"
}
# Ressource dans la région de backup
resource "aws_s3_bucket" "backup" {
provider = aws.backup
bucket = "mon-bucket-backup"
}lifecycle — contrôler le cycle de vie d’une ressource
resource "TYPE" "NOM" {
lifecycle {
create_before_destroy = true|false
prevent_destroy = true|false
ignore_changes = [ATTRIBUT, ...]
replace_triggered_by = [RESSOURCE_OU_ATTRIBUT, ...]
precondition { ... }
postcondition { ... }
}
}resource "aws_instance" "web" {
ami = var.ami
instance_type = "t3.micro"
lifecycle {
# Créer la nouvelle instance AVANT de détruire l'ancienne
# → zero downtime lors d'un remplacement
create_before_destroy = true
# Bloquer terraform destroy (protection des ressources critiques)
prevent_destroy = true
# Ignorer les changements sur ces attributs
# (utile quand des systèmes externes modifient ces valeurs)
ignore_changes = [
tags["LastModified"], # tag mis à jour automatiquement
user_data, # user_data géré en dehors de Terraform
]
}
}
# replace_triggered_by : recréer quand une autre ressource change
resource "aws_autoscaling_group" "app" {
launch_template {
id = aws_launch_template.app.id
version = aws_launch_template.app.latest_version
}
lifecycle {
replace_triggered_by = [
aws_launch_template.app.latest_version
]
}
}
# Precondition / Postcondition (TF 1.2+)
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
lifecycle {
precondition {
condition = data.aws_ami.ubuntu.architecture == "x86_64"
error_message = "L'AMI doit être x86_64."
}
postcondition {
condition = self.public_ip != ""
error_message = "L'instance doit avoir une IP publique."
}
}
}En relation avec
- HCL — Vue d’ensemble — hub syntaxe HCL
- Types et expressions — for_each utilise les types map et set
- Blocs fondamentaux — meta-arguments dans resource et module
- terraform plan — impact des meta-arguments sur le plan