Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Langage dédié ou généraliste pour décrire l'infrastructure

Par mis à jour le

Améliorer cette page

On peut décrire l'infrastructure dans un langage conçu pour cela (HCL, YAML) ou dans un langage de programmation généraliste (Python, TypeScript). Le premier limite ce que l'on peut écrire, donc ce qu'il faut relire. Le second offre boucles, fonctions et tests, au prix d'une liberté qui peut produire un code difficile à relire. Dans les deux cas, un moteur calcule un plan avant d'agir : le langage n'est qu'une façon de décrire l'état voulu. Cette leçon s'adresse à des personnes qui lisent du YAML et connaissent Git, et propose des critères pour choisir sans dogme.

Les extraits sont des illustrations à lire, pas des étapes à exécuter.

  • définir langage dédié et langage généraliste en IaC ;
  • expliquer pourquoi un plan est calculé quel que soit le langage ;
  • comparer ce que chaque famille apporte en tests et en lisibilité ;
  • repérer le risque de code trop abstrait et le limiter.

Reprenons l'équipe de quatre personnes qui gère une application web : deux VM applicatives, une base de données, un réseau et un DNS, en dev et en prod. Elle passe cette infrastructure en code (dev d'abord, prod ensuite) et doit choisir le langage.

Pour deux VM et une base, la question semble anodine. Elle devient importante quand l'équipe imagine ajouter un environnement de préproduction, puis un deuxième site : faut-il alors une boucle, une fonction réutilisable, une condition ? C'est précisément là que les deux familles de langages se distinguent.

Qu'est-ce qu'un langage dédié, et un langage généraliste ?

Section intitulée « Qu'est-ce qu'un langage dédié, et un langage généraliste ? »

Un langage dédié, en anglais DSL (domain-specific language), est conçu pour un seul usage : décrire un état voulu. Il offre un vocabulaire restreint (ressources, variables, sorties) et peu de structures de contrôle. HCL, le langage de Terraform et d'OpenTofu, en est un exemple. YAML utilisé par Ansible ou par les modèles CloudFormation joue le même rôle, avec parfois un moteur de gabarits (Jinja2) pour injecter de la logique.

Un langage généraliste est un langage de programmation complet, conçu pour tout type de programme : Python, TypeScript, Go, C#, Java. En IaC, des outils comme Pulumi permettent de décrire les ressources directement dans ces langages. L'AWS CDK fait de même pour AWS : le code Python ou TypeScript est transformé en modèle CloudFormation.

La différence n'est pas « déclaratif contre impératif » au sens strict. Un langage généraliste est impératif dans sa syntaxe, mais ce qu'il produit est une description d'état voulu. La distinction entre les deux approches est reprise dans Déclaratif vs impératif en Infrastructure as Code.

Que se passe-t-il vraiment derrière un code en Python ?

Section intitulée « Que se passe-t-il vraiment derrière un code en Python ? »

Le programme ne crée pas directement les machines. Quand il s'exécute, chaque ligne qui déclare une ressource enregistre une intention auprès d'un moteur. Une fois le programme terminé, le moteur détient la liste de ce qui doit exister, la compare à l'état connu du réel, puis calcule un plan : créations, modifications, remplacements, destructions.

C'est le même raisonnement que pour HCL, décrit dans État, plan et réconciliation. Un programme Pulumi produit un aperçu avant l'application ; l'AWS CDK produit un modèle CloudFormation dont le déploiement passe par défaut par un change set (méthode change-set de cdk deploy). Ce que vous relisez en revue, au bout du compte, c'est donc un plan, quelle que soit la source.

Cette propriété est précieuse : même si le code est élaboré, le plan reste le lieu de vérité sur ce qui va se passer. Elle explique aussi pourquoi il serait imprudent de ne relire que le code source dans une revue : le plan montre ce que le code produit réellement, ce que la lecture seule peut masquer.

Comment se présente le même besoin dans les deux familles ?

Section intitulée « Comment se présente le même besoin dans les deux familles ? »

Pour créer les deux VM applicatives, voici deux illustrations. La première est en HCL, avec un compteur. La seconde est en Python avec Pulumi. Elles sont à lire, pas à exécuter ; les noms de ressources et d'images sont fictifs.

resource "aws_instance" "app" {
count = 2
ami = var.image_app
instance_type = "t3.small"
tags = {
Name = "app-${count.index + 1}"
}
}
import pulumi_aws as aws
for i in range(2):
aws.ec2.Instance(
f"app-{i + 1}",
ami=image_app,
instance_type="t3.small",
)

Les deux déclarent deux machines identiques. En HCL, la répétition passe par un attribut du langage ; en Python, par une boucle for ordinaire. Pour ce besoin simple, le HCL est plus court à lire. L'écart se creuse quand la logique devient plus riche : choisir l'image selon l'environnement, générer des règles réseau à partir d'une liste, valider une entrée. Python y est plus à l'aise, mais chaque ligne de logique devient un endroit où se tromper.

Quels avantages et inconvénients pour chaque famille ?

Section intitulée « Quels avantages et inconvénients pour chaque famille ? »

Le choix se fait sur ce que l'équipe sait lire, relire et tester facilement.

CritèreLangage dédié (HCL, YAML)Langage généraliste (Python, TypeScript)
Courbe d'apprentissageFaible pour un petit vocabulaireDépend du niveau de programmation de l'équipe
RelectureUniforme : tout le monde écrit à peu près pareilVariable : plusieurs façons d'écrire la même chose
Logique (boucles, conditions)Limitée, parfois contournéeComplète
RéutilisationModules du langageFonctions, classes, paquets partagés
Aide de l'éditeurCorrecteExcellente (types, complétion, refactoring)
TestsTests propres à l'outilTests unitaires avec les outils habituels du langage
Risque principalContournements pénibles quand le besoin dépasse le langageCode trop abstrait, difficile à relire

Aucun des deux n'est supérieur dans l'absolu. Un langage dédié contraint et facilite ainsi la relecture ; un langage généraliste libère et exige davantage de discipline.

Les langages généralistes permettent d'écrire des tests unitaires : de petits tests automatiques qui vérifient une fonction isolée sans rien déployer. Par exemple, tester qu'une fonction qui calcule les règles réseau refuse une plage d'adresses invalide, ou qu'une VM porte bien les étiquettes obligatoires. Pulumi propose des tests unitaires avec des ressources simulées. Les outils à langage dédié ont leurs propres mécanismes, comme terraform test pour Terraform et tofu test pour OpenTofu.

Une limite doit rester claire : un test unitaire vérifie la logique de votre code, pas le comportement de l'infrastructure réelle. Il prouve que la fonction calcule bien la liste de règles, pas que le fournisseur les acceptera. Il complète le plan et les contrôles automatiques, il ne les remplace pas.

Tester coûte du temps, mais c'est justement ce qui rend raisonnable l'usage d'un langage riche : plus il y a de logique, plus elle mérite un test. Sans test, la souplesse d'un langage généraliste devient un risque. La pyramide complète des contrôles d'une chaîne IaC est traitée dans Tests et contrôles automatiques.

Qu'est-ce que le risque d'abstraction et de code trop malin ?

Section intitulée « Qu'est-ce que le risque d'abstraction et de code trop malin ? »

Un langage généraliste invite à abstraire : écrire une fonction qui génère tout un environnement à partir de quelques paramètres, une classe qui décide seule des règles réseau. Poussée trop loin, cette habileté produit du code que seul son auteur comprend.

Les symptômes sont reconnaissables. On ne devine plus combien de ressources un paramètre va créer. Un changement d'une ligne modifie trente ressources dans le plan. Les noms de ressources sont construits dynamiquement, donc introuvables par une recherche de texte. La logique d'une condition est enfouie sous trois niveaux d'appels.

Trois garde-fous aident à rester maîtrisable. D'abord, relire le plan plutôt que seulement le code : il liste ce qui change réellement. Ensuite, préférer la répétition lisible à une abstraction prématurée : deux blocs proches, mais clairs, valent mieux qu'une fonction à dix paramètres. Enfin, nommer explicitement les ressources et garder la logique courte, pour qu'une personne qui découvre le dépôt puisse suivre.

Ce risque existe aussi dans les langages dédiés : un module Terraform très paramétré ou un rôle Ansible bourré de conditions Jinja2 posent les mêmes problèmes (voir Anti-patterns des modules Terraform). La différence est de degré, pas de nature. Il rejoint la dette décrite dans Diagnostiquer puis prioriser la dette technique IaC, et un dépôt lisible, quel que soit le langage, relève de Organiser un projet IaC.

Pour une équipe qui débute avec deux VM, une base, un réseau et un DNS, un langage dédié est le choix le plus prudent : il impose un vocabulaire commun, se relit vite et ne tente pas de sur-ingénierie. L'équipe apprend à lire des plans avant d'apprendre à programmer l'infrastructure.

Un langage généraliste devient pertinent quand les développeurs de l'équipe écrivent déjà du Python ou du TypeScript et que la logique de l'infrastructure est riche : nombreux environnements générés, règles dérivées de données, besoin de tests unitaires systématiques. Dans ce cas, la formation Pulumi détaille la mise en pratique avec un langage généraliste, et Pulumi : preview, tests et CI montre l'aperçu et les tests dans une chaîne de CI.

Le choix n'est pas définitif, mais il engage les compétences de l'équipe et le coût de la relecture. Il mérite d'être écrit et justifié, ce qu'enseigne la leçon Documenter une décision d'infrastructure avec un ADR.

  • Un langage dédié (HCL, YAML) restreint ce que l'on écrit ; un langage généraliste (Python, TypeScript) offre une logique complète.
  • Derrière un code impératif, un moteur calcule toujours un plan à partir de l'état voulu : relisez ce plan, pas seulement le code source.
  • Un langage généraliste apporte fonctions, boucles et tests unitaires ; il demande plus de discipline.
  • Un test unitaire vérifie la logique du code, pas le comportement de l'infrastructure réelle.
  • Le code trop malin se reconnaît à des changements d'une ligne qui bougent des dizaines de ressources : préférez la répétition lisible à l'abstraction prématurée.
  • Pour une équipe qui débute, un langage dédié est le choix prudent ; un langage généraliste se justifie par les compétences et la complexité.

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn