Les types deviennent vraiment importants dès que vous écrivez des variables Terraform, des inputs Packer, des outputs ou des objets plus riches. Tant que vous ne manipulez que quelques chaînes simples, tout paraît facile. Dès qu’une configuration doit accepter une liste, une map ou un objet structuré, il faut savoir décrire précisément la forme attendue.
Cette page clarifie un point essentiel : dans l’écosystème Terraform, on mélange souvent valeurs HCL et contraintes de type. Les deux sont proches, mais ce n’est pas la même chose.
Valeur ou contrainte de type : ne pas confondre
Section intitulée « Valeur ou contrainte de type : ne pas confondre »Voici la distinction la plus utile à retenir :
| Vous écrivez | Ce que c’est | Exemple |
|---|---|---|
| une valeur | une donnée concrète | ["dev", "prod"] |
| une contrainte de type | la forme attendue pour une valeur | list(string) |
Exemple avec une variable Terraform :
variable "environments" { type = list(string) default = ["dev", "prod"]}list(string) n’est pas une valeur à déployer. C’est une contrainte de type. La valeur concrète est ["dev", "prod"].
La même logique s’applique dans Packer :
variable "packages" { type = list(string) default = ["curl", "jq"]}Les types primitifs
Section intitulée « Les types primitifs »Les trois types primitifs à connaître en premier sont :
variable "name" { type = string default = "vm-dev"}
variable "memory" { type = number default = 2048}
variable "enabled" { type = bool default = true}stringpour du texte ;numberpour des entiers ou décimaux ;boolpourtrueoufalse.
Terraform convertit parfois automatiquement certaines valeurs simples, mais cela ne doit pas vous inciter à laisser les types implicites quand un module ou une variable doit être claire.
Les collections courantes
Section intitulée « Les collections courantes »Une liste regroupe plusieurs valeurs du même type, dans un ordre donné.
variable "dns_servers" { type = list(string) default = ["1.1.1.1", "8.8.8.8"]}Une map associe des clés à des valeurs du même type.
variable "tags" { type = map(string) default = { env = "dev" team = "platform" }}Un set contient des valeurs uniques, sans ordre garanti. Il est pratique quand la duplication n’a pas de sens.
variable "availability_zones" { type = set(string) default = ["eu-west-3a", "eu-west-3b"]}Les structures plus riches
Section intitulée « Les structures plus riches »object({...})
Section intitulée « object({...}) »Un objet permet de définir plusieurs attributs nommés, chacun avec son propre type.
variable "vm" { type = object({ name = string memory = number vcpu = number })}Ce type est souvent le plus utile pour décrire une entrée structurée propre.
tuple([...])
Section intitulée « tuple([...]) »Un tuple décrit une séquence positionnelle où chaque élément peut avoir un type différent.
locals { metadata = ["vm-dev", 2048, true]}La contrainte correspondante serait :
tuple([string, number, bool])Dans la pratique courante, tuple est moins fréquent que list ou object, mais il aide à comprendre pourquoi Terraform distingue parfois les littéraux de collection et les types attendus.
map et object, list et tuple
Section intitulée « map et object, list et tuple »La documentation officielle Terraform rappelle que ces paires sont proches, mais pas identiques :
listdécrit une collection homogène ordonnée ;tupledécrit une collection ordonnée avec un type par position ;mapdécrit des clés nommées avec des valeurs homogènes ;objectdécrit des attributs nommés avec un type précis pour chacun.
Pour beaucoup de cas quotidiens, la différence est discrète. Elle devient importante quand vous écrivez des variables typées, des modules ou des validations fines.
L’attribut optional(...) dans un objet
Section intitulée « L’attribut optional(...) dans un objet »Terraform permet aussi de marquer certains attributs d’objet comme optionnels :
variable "vm" { type = object({ name = string memory = optional(number, 1024) tags = optional(map(string), {}) })}Ce mécanisme est très utile quand vous voulez offrir une interface de module plus souple sans abandonner le typage.
Le piège de any
Section intitulée « Le piège de any »any existe, mais la documentation officielle recommande de l’utiliser avec parcimonie.
variable "settings" { type = any}Ce choix n’est raisonnable que si vous traitez la valeur comme un bloc opaque, par exemple pour l’envoyer telle quelle dans un jsonencode. Si vous comptez lire ses attributs ou imposer une structure, décrivez plutôt le type attendu explicitement.
Quand ce guide suffit et quand passer à Terraform
Section intitulée « Quand ce guide suffit et quand passer à Terraform »Ce guide suffit si votre difficulté principale est de comprendre la forme des valeurs et des types. Passez ensuite aux guides Terraform ou Packer quand le sujet devient concret :
- Variables Terraform pour
default,validation,sensitiveettfvars; - Locals Terraform pour organiser des valeurs calculées ;
- Variables et fonctions Packer pour les entrées, locals et fichiers
.pkrvars.hcl; - Contraintes de version Terraform pour encadrer versions de Terraform, providers et modules.
À retenir
Section intitulée « À retenir »- Une valeur et une contrainte de type sont deux choses différentes.
string,numberetboolsont les bases.list,map,set,objectettupleservent à structurer des données plus riches.object({...})est souvent le meilleur choix pour décrire une entrée complexe de module.anydoit rester l’exception, pas la solution de facilité.