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

Variables et outputs Terraform

12 min de lecture

logo terraform

Votre configuration Terraform contient des valeurs en dur : nom de la VM, taille mémoire, chemin de l’image. Pour changer un paramètre, vous devez modifier le code. Si deux projets partagent la même structure mais des valeurs différentes, vous dupliquez tout le fichier.

Les variables résolvent ce problème en séparant la logique (le code HCL) des valeurs (les paramètres). Vous écrivez le code une seule fois dans main.tf, puis vous changez les valeurs dans terraform.tfvars sans toucher à la logique. Les locals centralisent les calculs réutilisés, et les outputs exposent les résultats après chaque apply.

Ce que vous allez apprendre :

  • Déclarer des variables typées avec validation dans variables.tf
  • Calculer des valeurs dérivées avec locals
  • Exposer des résultats avec output pour l’affichage et l’intermodule
  • Surcharger les valeurs avec terraform.tfvars, TF_VAR_* et -var

Prérequis : avoir suivi le guide Première infrastructure.

Sans variable :

resource "libvirt_domain" "vm" {
name = "lab02-vm" # en dur — impossible de réutiliser
memory = 512
}

Avec variable :

resource "libvirt_domain" "vm" {
name = var.vm_name # paramétrable
memory = var.memory
}

La séparation est nette : la logique reste dans main.tf, les valeurs vont dans terraform.tfvars.

Le projet se compose de six fichiers, chacun avec un rôle précis :

mon-projet/
├── versions.tf # Provider et version Terraform
├── variables.tf # Déclarations des variables d'entrée
├── locals.tf # Valeurs calculées (ne changent pas entre environnements)
├── main.tf # Ressources libvirt
├── outputs.tf # Ce que Terraform affiche après apply
└── terraform.tfvars # Valeurs concrètes (surchargent les defaults)

Cette organisation est une convention très répandue dans les projets Terraform. Elle n’est pas obligatoire — tout pourrait tenir dans un seul fichier — mais elle rend la navigation immédiate.

Dans variables.tf, chaque bloc variable {} déclare une entrée possible :

variable "vm_name" {
description = "Nom de la VM libvirt"
type = string
default = "lab02-vm"
validation {
condition = can(regex("^[a-z0-9-]+$", var.vm_name))
error_message = "Le nom de VM ne peut contenir que des minuscules, des chiffres et des tirets."
}
}
variable "memory" {
description = "RAM allouée en MiB"
type = number
default = 512
validation {
condition = var.memory >= 256 && var.memory <= 16384
error_message = "La mémoire doit être comprise entre 256 et 16384 MiB."
}
}
variable "vcpu" {
description = "Nombre de vCPUs"
type = number
default = 1
}
variable "image_path" {
description = "Chemin vers l'image cloud de base"
type = string
default = "~/images/ubuntu-24.04-cloudimg.img"
}
variable "pool" {
description = "Pool libvirt cible"
type = string
default = "default"
}

Anatomie d’une déclaration de variable :

ChampObligatoireRôle
descriptionRecommandéDocumente l’usage dans terraform console et les outils
typeRecommandéValide que la valeur fournie est du bon type
defaultFacultatifSi absent, Terraform demandera la valeur interactivement
validationFacultatifAjoute des contraintes métier vérifiées avant le plan

Les locals sont différents des variables : ils ne reçoivent pas de valeur de l’extérieur, ils calculent quelque chose à partir d’autres valeurs.

locals.tf
locals {
disk_name = "${var.vm_name}.qcow2"
vm_label = "lab02/${var.vm_name}"
}

Utilisez locals quand :

  • Une valeur est calculée à partir d’une variable mais n’a pas de sens à surcharger de l’extérieur.
  • La même expression apparaît à plusieurs endroits dans main.tf.

Dans main.tf, accédez aux variables avec le préfixe var. et aux locals avec local. :

resource "libvirt_volume" "disk" {
name = local.disk_name # "lab02-vm.qcow2" calculé par locals
pool = var.pool # valeur de la variable
target = { format = { type = "qcow2" } }
create = { content = { url = pathexpand(var.image_path) } }
}
resource "libvirt_domain" "vm" {
name = var.vm_name # "lab02-vm" par défaut
type = "kvm"
memory = var.memory # 512 MiB par défaut
memory_unit = "MiB"
vcpu = var.vcpu
os = { type = "hvm", type_arch = "x86_64", type_machine = "q35" }
devices = {
disks = [{
source = { file = { file = libvirt_volume.disk.path } }
target = { dev = "vda", bus = "virtio" }
}]
interfaces = [{
model = { type = "virtio" }
source = { network = { network = "default" } }
}]
}
}

Les outputs affichent des informations utiles après le apply et peuvent être utilisés par d’autres modules Terraform :

outputs.tf
output "vm_name" {
description = "Nom de la VM créée"
value = libvirt_domain.vm.name
}
output "vm_memory" {
description = "RAM allouée en MiB"
value = libvirt_domain.vm.memory
}
output "disk_path" {
description = "Chemin du volume disque créé"
value = libvirt_volume.disk.path
}
output "vm_label" {
description = "Label calculé par locals"
value = local.vm_label
}

Les outputs ne servent pas seulement à l’affichage. Quand un module appelle un autre module, les outputs sont le seul moyen de récupérer des valeurs calculées.

  1. Appliquez avec les valeurs par défaut :

    Fenêtre de terminal
    cd ~/terraform-variables-outputs
    terraform init
    terraform apply -auto-approve

    Terraform affiche les outputs à la fin :

    Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
    Outputs:
    disk_path = "/var/lib/libvirt/images/lab02-vm.qcow2"
    vm_label = "lab02/lab02-vm"
    vm_memory = 512
    vm_name = "lab02-vm"
  2. Surchargez une variable en ligne de commande :

    Fenêtre de terminal
    terraform apply -var="vm_name=mon-test" -var="memory=1024" -auto-approve

    Terraform crée une nouvelle VM nommée mon-test avec 1 Go de RAM. Les variables non mentionnées gardent leur valeur par défaut.

  3. Utilisez un fichier terraform.tfvars pour des valeurs permanentes :

    terraform.tfvars
    vm_name = "lab02-custom"
    memory = 1024
    vcpu = 2

    Terraform charge automatiquement terraform.tfvars s’il existe dans le répertoire courant. Ne mettez pas ce fichier dans git s’il contient des données sensibles (tokens, mots de passe).

  4. Détruisez le lab :

    Fenêtre de terminal
    terraform destroy -auto-approve

Quand une variable est définie à plusieurs endroits, Terraform applique cet ordre (du moins prioritaire au plus prioritaire) :

default dans variables.tf
< fichier .tfvars
< variable d'environnement TF_VAR_nom
< flag -var en ligne de commande

Un -var=... écrase tout le reste. C’est utile pour les scripts CI/CD qui injectent des valeurs sans modifier les fichiers.

Après un apply, vous pouvez ré-afficher les outputs sans refaire un plan :

Fenêtre de terminal
terraform output
terraform output vm_name # valeur spécifique
terraform output -json # format JSON pour les scripts
  • Les variables (variable {}) externalisent les valeurs configurables. Les defaults rendent les variables optionnelles.
  • Les locals (locals {}) calculent des valeurs dérivées réutilisables dans main.tf.
  • Les outputs (output {}) exposent des informations après chaque apply.
  • terraform.tfvars centralise les valeurs d’un environnement sans modifier le code.
  • L’ordre de priorité : default < .tfvars < TF_VAR_* < -var.

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