
Un module sans variables est figé. Un module sans outputs est isolé. Les variables sont le mécanisme qui rend un module paramétrable — chaque appel peut fournir des valeurs différentes. Les outputs sont le mécanisme qui rend les résultats accessibles — sans eux, la configuration racine ne peut rien lire des ressources créées par le module.
Ce guide approfondit ces deux mécanismes : types simples et complexes (dont object), validations personnalisées, valeurs par défaut, et outputs structurés.
Prérequis : avoir lu Créer un module Terraform et Structure d’un module.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Utiliser les types simples (
string,number,bool) et complexes (object) - Valider les entrées avec des règles personnalisées
- Distinguer variables obligatoires et optionnelles via
default - Exposer des outputs structurés depuis un module
- Lire les outputs d’un module depuis la configuration racine
Les variables : les entrées du module
Section intitulée « Les variables : les entrées du module »Anatomie d’une variable
Section intitulée « Anatomie d’une variable »Chaque variable se déclare dans variables.tf avec cette structure :
variable "nom" { type = string # ↑ le type de donnée attendu description = "Nom du réseau libvirt" # ↑ documentation pour l'utilisateur du module default = "mon-reseau" # ↑ optionnel : si présent, la variable est optionnelle}| Attribut | Rôle | Obligatoire |
|---|---|---|
type | Type de la valeur attendue | Recommandé (sinon any) |
description | Explication pour l’utilisateur | Recommandé |
default | Valeur par défaut | Non — sans default, la variable est obligatoire |
validation | Règle de vérification personnalisée | Non |
Types simples
Section intitulée « Types simples »Les trois types de base couvrent la majorité des cas :
variable "nom" { type = string # ↑ texte : "dev-network", "10.10.80.0"}
variable "memoire" { type = number default = 512 # ↑ nombre entier ou décimal : 512, 1024, 2.5}
variable "activer_dns" { type = bool default = true # ↑ vrai ou faux : true, false}Type object — regrouper des paramètres liés
Section intitulée « Type object — regrouper des paramètres liés »Quand plusieurs variables forment un ensemble cohérent, le type object les regroupe en une seule structure :
La logique est : « plutôt que 3 variables séparées (adresse, masque, passerelle), je crée une variable unique cidr qui contient les trois ».
variable "cidr" { type = object({ adresse = string masque = string }) description = "Bloc CIDR du réseau (adresse + masque)"}L’appelant passe les valeurs en bloc :
module "reseau_dev" { source = "./modules/reseau" nom = "dev-vars"
cidr = { adresse = "10.10.84.0" masque = "255.255.255.0" } # ...}Dans le module, on accède aux champs avec la notation pointée :
resource "libvirt_network" "this" { # ... ips = [{ address = var.cidr.adresse # ↑ var.NOM_VARIABLE.CHAMP netmask = var.cidr.masque }]}Obligatoire vs optionnel
Section intitulée « Obligatoire vs optionnel »La présence ou l’absence de default détermine si l’appelant doit fournir la valeur :
variable "nom" { type = string # Pas de default → OBLIGATOIRE # L'appelant doit écrire : nom = "mon-reseau"}
variable "activer_dns" { type = bool default = true # default présent → OPTIONNEL # Si l'appelant ne le spécifie pas, la valeur sera true}Si une variable obligatoire est omise, Terraform refuse de continuer :
Error: No value for required variable on main.tf line 1: The input variable "nom" is not set.Valider les entrées
Section intitulée « Valider les entrées »Les blocs validation permettent de rejeter des valeurs invalides avant le terraform plan, avec un message d’erreur personnalisé :
variable "nom" { type = string description = "Nom du réseau libvirt"
validation { condition = length(var.nom) >= 3 && length(var.nom) <= 30 # ↑ expression booléenne : doit être true pour être valide error_message = "Le nom doit contenir entre 3 et 30 caractères." # ↑ message affiché si la condition est false }}Résultat avec nom = "ab" :
Error: Invalid value for variable on main.tf line 3, in module "reseau": 3: nom = "ab" │ var.nom is "ab"Le nom doit contenir entre 3 et 30 caractères.La validation avec contains est utile pour les valeurs à choix multiples :
variable "mode_forward" { type = string default = "nat"
validation { condition = contains(["nat", "route", "bridge", "none"], var.mode_forward) error_message = "Le mode doit être nat, route, bridge ou none." }}Résultat avec mode_forward = "invalide" :
Error: Invalid value for variable on main.tf line 12, in module "reseau": 12: mode_forward = "invalide" │ var.mode_forward is "invalide"Le mode doit être nat, route, bridge ou none.Les outputs : les sorties du module
Section intitulée « Les outputs : les sorties du module »Pourquoi les outputs sont indispensables
Section intitulée « Pourquoi les outputs sont indispensables »Sans outputs, les ressources créées par un module sont invisibles pour l’appelant. Même si le module crée un réseau avec un UUID, la configuration racine ne peut pas lire cet UUID — sauf si le module l’expose via un output.
Les outputs servent à :
- Afficher des informations après
terraform apply - Chaîner des modules entre eux (l’output de l’un devient l’input de l’autre)
- Exporter des données pour des scripts ou d’autres outils
Output simple
Section intitulée « Output simple »output "id" { value = libvirt_network.this.id # ↑ la valeur exposée (attribut d'une ressource) description = "UUID du réseau créé"}Output structuré (object)
Section intitulée « Output structuré (object) »Un output peut renvoyer un objet complet — utile pour résumer la configuration :
output "configuration" { value = { adresse = var.cidr.adresse masque = var.cidr.masque dns_actif = var.activer_dns mode = var.mode_forward } description = "Résumé de la configuration réseau"}Résultat de terraform output reseau_config :
{ "adresse" = "10.10.84.0" "dns_actif" = true "masque" = "255.255.255.0" "mode" = "nat"}Le format JSON est aussi disponible avec terraform output -json reseau_config :
{"adresse":"10.10.84.0","dns_actif":true,"masque":"255.255.255.0","mode":"nat"}Lire un output de module
Section intitulée « Lire un output de module »Depuis la configuration racine, la syntaxe est :
module.<NOM_DU_BLOC>.<NOM_OUTPUT>Exemple concret :
output "reseau_id" { value = module.reseau_dev.id # ↑ module.reseau_dev = nom du bloc module # ↑ .id = nom de l'output dans le module}
output "reseau_config" { value = module.reseau_dev.configuration}Chaîner des modules via les outputs
Section intitulée « Chaîner des modules via les outputs »L’utilisation la plus puissante des outputs est le chaînage de modules : l’output d’un module devient l’input d’un autre.
module "reseau" { source = "./modules/reseau" nom = "infra-lab" # ...}
module "vm" { source = "./modules/vm" network_name = module.reseau.nom # ↑ l'output "nom" du module reseau # devient l'input "network_name" du module vm}Terraform détecte automatiquement cette dépendance : il créera le réseau avant la VM, sans avoir besoin de depends_on.
Récapitulatif des types
Section intitulée « Récapitulatif des types »| Type | Exemple de valeur | Cas d’usage |
|---|---|---|
string | "dev-network" | Noms, adresses IP, chemins |
number | 512, 2.5 | Mémoire, CPU, compteurs |
bool | true, false | Activation/désactivation de fonctionnalités |
list(string) | ["a", "b"] | Listes de noms, de tags |
map(string) | {env = "dev"} | Paires clé-valeur |
object({...}) | {adresse = "...", masque = "..."} | Structures avec champs nommés et typés |
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
No value for required variable | Variable sans default non fournie | Ajouter l’argument dans le bloc module |
Invalid value for variable | La validation a rejeté la valeur | Lire le error_message et corriger la valeur |
This object does not have an attribute named "X" | Tentative de lire un output inexistant | Vérifier le nom dans outputs.tf du module |
Unsuitable value type | Mauvais type passé (string au lieu de number) | Vérifier le type dans variables.tf |
module.X.Y vide | L’output existe mais la ressource n’a pas encore été créée | Relancer terraform apply |
À retenir
Section intitulée « À retenir »- Les variables sont les entrées d’un module — elles le rendent paramétrable
- Sans
default, une variable est obligatoire ; avecdefault, elle est optionnelle - Le type
objectregroupe des paramètres qui forment un ensemble cohérent - Les
validationbloquent les valeurs invalides avant leplan, avec un message clair - Les outputs sont les sorties — sans eux, les ressources du module sont invisibles
- Le chaînage de modules passe par les outputs :
module.A.output_name→ input du module B - Terraform crée automatiquement les dépendances entre modules chaînés