Aller au contenu
Infrastructure as Code medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Les fonctions Terraform : transformer et composer les valeurs

11 min de lecture

logo terraform

Comment construire le nom lab03-web-0 à partir de variables séparées ? Comment lire un fichier cloud-init et l’encoder en base64 ? Comment fusionner deux maps de tags sans les réécrire ? Ces transformations reviennent dans chaque projet Terraform.

Terraform embarque plus de 100 fonctions intégrées directement dans HCL, sans import, sans module externe. Elles ne modifient pas l’infrastructure — elles transforment des valeurs dans votre code : construire un nom de ressource avec format(), calculer une mémoire arrondie avec ceil(), fusionner des maps avec merge(), lire un fichier avec file(). Elles s’utilisent principalement dans les locals, les outputs, et les attributs de ressources. Maîtriser les fonctions les plus courantes réduit la duplication et rend les configurations plus expressives et maintenables.

  • terraform console : tester des fonctions interactivement
  • Fonctions de chaînes : format, upper, lower, replace, trimspace, split, join
  • Fonctions numériques : ceil, floor, min, max
  • Fonctions de listes : length, element, sort, contains, toset
  • Fonctions de maps : keys, values, merge, lookup
  • Fonctions de fichiers : file, templatefile, base64encode

Avant d’intégrer une fonction dans votre code, testez-la avec la console interactive Terraform :

Fenêtre de terminal
terraform console
> upper("lab06-vm")
"LAB06-VM"
> format("%s-%s.qcow2", "dev", "lab06-vm")
"dev-lab06-vm.qcow2"
> min(256, 512, 1024)
256
> exit

Sans accès à un projet initialisé, passez les expressions en stdin :

Fenêtre de terminal
echo 'upper("lab06-vm")' | terraform console
"LAB06-VM"

format — construire une chaîne avec des placeholders

Section intitulée « format — construire une chaîne avec des placeholders »
locals {
disk_name = format("%s-%s.qcow2", var.environment, var.vm_name)
# "dev-lab06-vm.qcow2"
}

Placeholders courants : %s (string), %d (entier), %f (flottant), %v (valeur quelconque).

locals {
vm_name_upper = upper(var.vm_name) # "LAB06-VM"
vm_name_lower = lower(var.vm_name) # "lab06-vm"
}

Utile pour normaliser les noms avant de les passer à une ressource.

locals {
hostname_replaced = replace(var.vm_name, "-", "_")
# "lab06_vm"
}
locals {
hostname_trimmed = trimspace(" dev-lab06-vm ")
# "dev-lab06-vm"
}
Fenêtre de terminal
echo 'split(",", "dev,staging,prod")' | terraform console
tolist([
"dev",
"staging",
"prod",
])
locals {
joined_envs = join(", ", ["dev", "staging", "prod"])
# "dev, staging, prod"
}

split et join sont souvent utilisés ensemble pour transformer des valeurs reçues en variable (une chaîne CSV → liste, ou l’inverse).

locals {
memory_gib = ceil(local.memory_mib / 1024) # ceil(0.5) → 1
disk_gb = floor(3.758) # → 3
}

ceil arrondit au supérieur, floor à l’inférieur.

locals {
min_memory = min(256, 512, 1024) # 256
max_memory = max(256, 512, 1024) # 1024
}

Combinés avec des data sources, ils permettent de borner des valeurs calculées dynamiquement — comme dans le guide sur les data sources.

locals {
environments = ["dev", "staging", "prod"]
env_count = length(local.environments) # 3
}
locals {
first_env = element(local.environments, 0) # "dev"
}

Si l’index dépasse la taille de la liste, element reboucle (modulo). Pour un accès strict, préférez la syntaxe liste[index].

locals {
sorted_envs = sort(["dev", "staging", "prod"])
# ["dev", "prod", "staging"]
}

Tri alphabétique. Pour les listes de nombres, utilisez les sorties de range() ou triez via sort([ for x in ... : tostring(x) ]).

Fenêtre de terminal
echo 'contains(["dev","prod"], "dev")' | terraform console
true

Utilisé pour valider des variables en precondition ou dans des expressions conditionnelles.

Fenêtre de terminal
echo 'toset(["b","a","a","c"])' | terraform console
toset([
"a",
"b",
"c",
])

toset supprime les doublons et trie les éléments. Indispensable avant d’utiliser for_each (qui requiert un set ou une map).

variable "tags" {
type = map(string)
default = { projet = "demo", equipe = "devops", auteur = "terraform" }
}
locals {
tag_keys = keys(var.tags) # ["auteur", "equipe", "projet"]
tag_values = values(var.tags) # ["terraform", "devops", "demo"]
}

Les clés sont retournées triées alphabétiquement.

locals {
tags_merged = merge(var.tags, { env = var.environment })
# {auteur="terraform", env="dev", equipe="devops", projet="demo"}
}

En cas de clé dupliquée, la dernière map gagne. Pratique pour ajouter des tags dynamiques à un socle de tags communs.

Résultat réel :

tags_merged = {
"auteur" = "terraform"
"env" = "dev"
"equipe" = "devops"
"projet" = "demo-fonctions"
}
Fenêtre de terminal
echo 'lookup({"a"="alpha","b"="beta"}, "a", "défaut")' | terraform console
"alpha"

lookup(map, clé, défaut) retourne la valeur ou le défaut si la clé est absente. Utile pour des mappings conditionnels :

locals {
instance_size = lookup({
dev = "small"
staging = "medium"
prod = "large"
}, var.environment, "small")
}
locals {
coalesced = coalesce("", "", "première valeur non vide", "autre")
# "première valeur non vide"
}

coalesce retourne le premier argument non vide (non null, non ""). Excellent pour les valeurs optionnelles avec fallback.

Fenêtre de terminal
echo 'jsonencode({"cle"="valeur","nb"=42})' | terraform console
"{\"cle\":\"valeur\",\"nb\":42}"

jsonencode est utilisé pour passer des structures complexes là où une chaîne JSON est attendue (user_data cloud-init, policies IAM…).

resource "libvirt_domain" "vm" {
# ...
# Lire une clé SSH publique depuis un fichier
# user_data = file("${path.module}/cloud-init.yml")
}

file(chemin) lit le fichier et retourne son contenu comme une chaîne. Le chemin est relatif à la racine du module.

locals {
user_data = templatefile("${path.module}/cloud-init.yml.tpl", {
hostname = local.hostname
ssh_key = file("~/.ssh/id_rsa.pub")
})
}

templatefile(chemin, vars) lit un fichier template et substitue les variables. C’est la façon recommandée d’injecter de la configuration (cloud-init, scripts shell) dans les ressources.

locals {
user_data_b64 = base64encode(file("${path.module}/cloud-init.yml"))
}

Certains providers attendent user_data en base64. base64encode (et son inverse base64decode) gèrent cette conversion.

coalesced = "première valeur non vide"
disk_gb = 3
disk_name = "dev-lab06-vm.qcow2"
env_count = 3
first_env = "dev"
hostname = "dev-lab06-vm"
hostname_replaced = "lab06_vm"
joined_envs = "dev, staging, prod"
max_memory = 1024
memory_gib = 1
min_memory = 256
sorted_envs = tolist([
"dev",
"prod",
"staging",
])
tag_keys = tolist([
"auteur",
"equipe",
"projet",
])
tags_merged = {
"auteur" = "terraform"
"env" = "dev"
"equipe" = "devops"
"projet" = "demo-fonctions"
}
vm_name_upper = "LAB06-VM"
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
CatégorieFonctions clés
Chaînesformat, upper, lower, replace, trimspace, split, join, substr, startswith, endswith
Nombresceil, floor, min, max, abs, pow, signum
Listeslength, element, sort, contains, toset, flatten, concat, distinct, range
Mapskeys, values, merge, lookup, zipmap, tomap
Fichiersfile, templatefile, base64encode, base64decode, filebase64
Encodage/typesjsonencode, jsondecode, tostring, tonumber, tobool
Logiquecoalesce, coalescelist, one

La référence complète est disponible dans la documentation officielle Terraform.

SymptômeCause probableSolution
Error: Invalid function argumentMauvais type passé à la fonctionVérifier avec terraform console
Error: Call to unknown functionFaute de frappe sur le nomLes fonctions sont en minuscules sans tirets
null retourné par lookupClé absente et pas de défautAjouter un troisième argument (valeur par défaut)
toset change l’ordreComportement normalLes sets ne garantissent pas l’ordre d’insertion
  1. terraform console est le meilleur outil pour tester une fonction avant de l’intégrer
  2. format() construit des chaînes complexes — à préférer à l’interpolation ${} pour les cas multi-parties
  3. merge() combine des maps — en cas de doublon, la dernière map gagne
  4. toset() déduplique et trie — obligatoire avant for_each
  5. templatefile() est la méthode recommandée pour injecter cloud-init ou des scripts
  6. Les fonctions s’utilisent dans locals, outputs, et directement dans les attributs de ressources

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn