Journal Dhall, une réponse au problème de configuration

17
20
mai
2020

Sommaire

Cher Journal,

Ne te fie pas à l’intitulé, « le problème » n’est qu’un condensé fourre-tout pour ce qui est connu en tant que “Software Configuration Management issues” dans la lingua veicolare de la sphère informatique. Quant à Dhall, il s’agit d’un langage spécialisé dans la gestion de configurations1.

Présentation

Condensé en deux ou trois paragraphes

Dhall est un outil primordialement destiné à programmer les fichiers de configuration. En acronymes de moins de cinq lettres, tu as certainement entendu parler de formats comme INI, XML, JSON, YAML, TOML. Ils ont le point commun de ne pas être programmable. Différents degrés de programmabilité présentent différents atouts, entre autres la réduction des répétitions, la réutilisation ailleurs de portions produites dans un endroit initial, …

Un fichier .dhall à la fois exprime de la configuration et constitue une expression dans le langage de programmation Dhall. Cette expression sera in fine réduite, normalisée, après un processus d’évaluation, lequel processus est garanti de prendre cours pendant un temps fini. Par conséquent, peu importe l’expressivité, la technicité, … d’une expression Dhall, elle finira par être aplatie sous forme de valeurs basiques, id est telles que définies par le standard. Les expressions sont typées et les types standard dans la version actuelle sont sommairement listés ici-bas.

  1. Bool : booléens
  2. Natural : nombres entiers naturels (positifs, non-signés)
  3. Integer : nombres entiers signés
  4. Double : nombres décimaux
  5. Text : du texte
  6. List : tableaux, listes chaînées de valeurs partageant le même type
  7. Optional : variants, sommes
  8. Record : produits

En plus des types, le langage

  • permet d’exprimer des expressions intermédiaires sous forme de let … in ….
  • est muni d’une bibliothèque standard.

Caractéristiques conceptuelles

L’auteur originnel est Gabriel GONZALEZ (lien en HTTP) et certains choix reflètent des idées qui lui sont chères. Néanmoins, beaucoup d’autres personnes ont contribué au langage depuis son inception et cette sous-section se contentera de faire des constats sans chercher à les attribuer à Gabriel et ali.

Dhall a un typage fort et statique : une expression est correctement typée ou ne l’est pas et cela se voit très tôt ; il n’y a pas de contournements possibles pour essayer de retarder la vérification de types. Cela étant dit, tout est abondamment documenté, même les erreurs. La manière dont le langage évolue (quelle variété de typage, quelle fonction, … ajouter) ne dépend pas tant des avancées dans les systèmes de types, mais plutôt de la motivation plus ou moins avouée de la communauté autour : remplacer les systèmes de configurations non-programmables les plus en vogue, nommément JSON, YAML et TOML. Eh oui, mon journal, Gabriel et ali ont des opinions ! Ces soubassements dévoilés, il sera plus compréhensible de voir le foisonnement d’exemples liés à JSON et YAML dans diverses pages de la documentation upstream.

Un des choix prépondérant du langage est la limitation explicite des opérations possibles sur du texte. Plus précisément, une seule opération est permise : la concaténation. Ainsi ne peut-on pas comparer deux valeurs de types Text ou en calculer la taille en caractères. Encore une fois, derrière ce choix se trouve l’accent mis sur la capacité de bannir des catégories d’erreurs dès la vérification de types.

Un autre choix de poids garantit que tout opérateur

  1. est associatif, c'est-à-dire qu’il est superflu de préciser la priorité selon laquelle ses arguments seront évalués; par exemple, si a est de type Natural (a : Natural) ainsi que b : Natural et c : Natural, alors on peut additionner les trois avec l’opérateur + en faisant (a + b) + c ou a + (b + c) et les deux expressions équivalent à a + b + c.
  2. est muni d’une valeur nulle, un élément neutre, un zéro, valable dans toute l’étendue du type pour lequel il est défini. Exemples sous la notation (opérateur, zéro):
  • (*, 1) dans Natural et Integer,
  • (∧, {=}) dans Record,
  • (==, True) dans Boolean.

Derrière ces restrictions se trouve la nécessité de garantir que le résultat de l’application d’un opérateur aura le même type que les arguments qui y auront contribué ; c’est une nécessité propre à Dhall … J’ai mentionné plus haut qu’il est impossible de comparer deux valeurs de type Text ; cela est ainsi parce que (a : Text) == (b : Text) donnerait un c : Bool, une valeur de type différent de celui des valeurs de départ.

Puisqu’on parle de fichiers de configuration, il sautera aux yeux que ces restrictions sont incompatibles avec la manière dont on conçoit les tableaux associatifs ou dictionnaires, structures de données omniprésentes dans les configurations : avant de modifier de telles structures, des comparaisons d’égalité s’imposent. Un examen attentif du type Record couplé avec des fonctions de la bibliothèque standard permettent de lever l’apparente rigidité du langage.

Syntaxe et exemple plutôt dépouillé

Persée, Dictys, et Méduse forment une équipe chargée d’assurer les cours à distance d’une classe covid-confinée. Cassiopée est en charge de l’infrastructure sur laquelle tout cela reposera et, pour diverses raisons, décide que chaque membre du triptyque devrait avoir une configuration afin de garantir les conditions suivantes.

  • Pour un jour donné, indiquer une plage horaire pendant laquelle ses activités seront accomplies.
  • Énoncer d’emblée quels sont les thèmes que son cours abordera.
  • Déposer des documents supplémentaires potentiels et laisser Cassiopée en faire la distribution à l’audience.

Cassiopée est bien sûr Dhall-iste, découpe temporellement les choses en termes de semaines et prototype ses actions ainsi (juste un extrait) :

-- Fichier: a.dhall
{
      semaine   : Natural
    , personnel : List Text
}

Comme indiqué précédemment, le type d’une valeur est indiqué par deux points. Les annotations de types ne sont pas partout requis, Dhall inférant les types pour tous les cas non-ambigus ou non-spéciaux. Tout ce qui est dans ce fichier a.dhall est facultatif à Dhall mais est aussi valide. semaine est un nombre entier naturel, personnel un tableau dans lequel chaque élément est une valeur textuelle. Remarquons que

  • l’expression finale est une valeur anonyme de type Record, ce qu’indique les accolades ;
  • l’indentation est laissée à l’appréciation de tout le monde ;
  • les commentaires mono-lignes sont préfixées par deux tirets successifs.

Pour évaluer le fichier, utilisons par exemple le binaire dhall dans le Shell (Bash de ce côté ; les sorties sont en commentaires) :

dhall --file 'a.dhall'
# {  personnel : List Text, semaine : Natural }

Au lieu de types, traitons de valeurs.

-- Fichier: b.dhall
let per = "Persée" 
let dic = "Dictys" : Text

in {
      semaine   = 20
    , personnel = [per, dic, "Méduse"]
}

dhall dit que nous sommes toujours dans les clous:

dhall --file 'b.dhall'
# { personnel = [ "Persée", "Dictys", "Méduse" ], semaine = 20 }

dhall --annotate --file 'b.dhall'
#   { personnel = [ "Persée", "Dictys", "Méduse" ], semaine = 20 }
# : { personnel : List Text, semaine : Natural }

Constatons que l’évaluation a normalisé les entrées puisqu’en plus de la suppression du commentaire, les indirections let … in ont également disparues. L’expression reste une valeur anonyme de type Record. let introduit des variables visibles à l’intérieur de in.

Pour en finir avec cette démo, parlons des fonctions. La syntaxe à la Curry, le calcul lambda — ou toute autre expression par laquelle, ô journal !, tu serais déjà accoutumé à ce qui suit — alors, cette syntaxe permet de considérer que n’importe quelle fonction possède un seul argument. S’il y en a effectivement un, tant mieux, on l’applique: fct arg : ceci est un appel de la fonction fct sur le paramètre arg. S’il y en a plusieurs, on applique le premier argument à la fonction et on retourne une fonction anonyme qui prendra le reste des arguments et continuera le processus d’applications jusqu’à l’aboutissement d’une forme aplatie, normalisée. Le Robert me dit qu’un péquin est une personne quelconque, une personne lambda; par analogie, une fonction quelconque, anonyme, est aussi appelée fonction lambda. Voyons où ce détour nous mène :

-- Fichier: c.dhall
let precedemment   = ./b.dhall
let dossier_global = "/home/cours/"
let creer_dossier  = λ(val : Text)  dossier_global ++ val ++ "/"
let ajouter_theme  = λ(ind : Text)  λ(thm : Text)  creer_dossier ind ++ thm

in
    { thematiques =
        [ creer_dossier "Persée"
        , creer_dossier "Dictys"
        , ajouter_theme "Méduse" "Que racontait Zarathoustra ?" ]

    }  precedemment
  • precedemment a capturé une ressource, une URI. Ici, c’était un fichier indiqué par un chemin relatif. La ressource pouvait aussi être adressée par un chemin absolu ou une URL sur le WWW ; dans ce dernier cas, l’évaluation de l’expression aurait nécessité de la connexion Internet.
  • creer_dossier est un synonyme à la fonction lambda qui prend un seul argument et y applique deux concaténations grâce à l’opérateur ++.
  • ajouter_theme est un synonyme à une autre fonction anonyme qui prend deux arguments et fait usage de la fonction creer_dossier.
  • Le Record anonyme en cours de création est concaténée au Record créé ailleurs, dans le fichier b.dhall. La fusion des deux est accomplie par l’application de l’opérateur .
  • L’usage de l’Unicode est laissée à l’appréciation de tout le monde.
  • L’expression finale est celle-ci:
dhall --file 'c.dhall'
# { personnel = [ "Persée", "Dictys", "Méduse" ]
# , semaine = 20
# , thematiques =
#   [ "/home/cours/Persée/"
#   , "/home/cours/Dictys/"
#   , "/home/cours/Méduse/Que racontait Zarathoustra ?"
#   ]
# }

dhall type --file 'c.dhall'
# { personnel : List Text, semaine : Natural, thematiques : List Text }

Bref, nous avons obtenu un tout-bête fichier de configuration. Qu’en est-il des plages horaires et les plans sur la comète de Cassiopée ? Ah, journal !, tu l’as vu venir : « Cela est laissé en tant qu’exercice … »

Cette sous-section a commencé en attribuant toutes les choses qui allaient apparaître à Cassiopée ; je tiens à préciser que tout malentendu, toute imprécision ne sont dus qu’à moi ; Cassiopée, Dhall, … sont quittes.

Implémentations et interopérabilité

Un langage qui ne cache pas vouloir en remplacer d’autres doit se doter d’outils de migration. Sans même parler de migration, ces outils permettent de juste satisfaire la curiosité de personnes qui sont habituées à autre chose. Dans cette optique, il existe un certain nombre de binaires et bibliothèques qui effectuent la conversion dhall-to-FOO ou Foo-to-dhall. En témoin ces deux-là :

  • YAML: dhall-to-yaml --file 'c.dhall'
personnel:
  - "Persée"
  - Dictys
  - "Méduse"
semaine: 20
thematiques:
  - "/home/cours/Persée/"
  - /home/cours/Dictys/
  - "/home/cours/Méduse/Que racontait Zarathoustra ?"
  • JSON: dhall-to-json --file 'c.dhall'
{
  "personnel": [
    "Persée",
    "Dictys",
    "Méduse"
  ],
  "semaine": 20,
  "thematiques": [
    "/home/cours/Persée/",
    "/home/cours/Dictys/",
    "/home/cours/Méduse/Que racontait Zarathoustra ?"
  ]
}

Il y a même un dhall-to-yaml-ng produisant une autre variété de YAML.

Dhall a un standard et des implémentations diverses. À cette date, il y en a de matures en Clojure, Eta, Haskell, Java, Go, Nix, Ruby, et Rust.

Quant à la portabilité du langage sur des architectures matérielles, j’invoquerai un seul mot: Go. Une norme qui est implémentée dans ce langage se voit de facto portée sur une galaxie d’architectures. Je te vois venir, journal ! Je suis d’accord avec toi sur les problématiques liées à la taille et la puissance de Google ; à vrai dire, mon Go-innumérisme est même immensurable. Cependant, le binaire go qui se trimbale sur cette machine dit des choses que je ne peux pas ignorer :

# Combien d’architectures supporte golang?
go tool dist list | wc --lines
# 43

Dans la liste des implémentations, il y a Nix, un langage et ensembles d’outils qui sont, disons, des super-ensembles de Dhall à maints égards. Ça mérite une mention mais je préfère ne pas ouvrir un autre potentiel front après Go …

Approfondir le sujet

Voici une collection de liens triés subjectivement par ordre décroissant de pertinence :

Gabriel dira à qui veut entendre que Dhall est Turing-incomplet. Pourquoi insister ? Voici en HTTP ce qu’il a à dire sur ce sujet.

Par ailleurs, d’aucuns diront que YAML est bien comme il est, n’est-ce pas ? Et si on adoptait une approche diamétralement opposée en se débarrassant complètement des fichiers de configuration ? Il se trouve que nous avons des langages de programmation pour … programmer, notamment les fichiers de configurations. Et toi, journal, penses-tu que, sic, “[…] configs suck?”


  1. J’ai commis ce texte sous CC by SA 4.0 

  • # Où est l'intérêt ?

    Posté par . Évalué à 7 (+6/-0).

    J'ai beau avoir lu le journal, je ne comprend absolument pas l'intérêt du truc. La syntaxe est tellement peu lisible pour de la config …

    Perso moi c'est l'inverse, je peste dès que je croise un logiciel qui utilise un langage de programmation comme syntaxe de configuration (Ejabberd, Prosody par exemple)

    Ceux en charge du déploiement ne sont pas ceux en charge du développement. Ils n'ont pas besoin de connaître les syntaxes (qui parfois paraissent complètement absurdes) des langages utilisés. Et la lisibilité d'une fichier de config est hyper importante aussi.

    Bref, je suis partisan du YAML pour la conf (qui est à la fois lisible par un humain, et facilement parsable pour une machine)

    • [^] # Re: Où est l'intérêt ?

      Posté par (page perso) . Évalué à 3 (+2/-0). Dernière modification le 20/05/20 à 15:35.

      Et on constate que l'utilisation d'outils comme ansible a amené d'autres usages. Le côté « programmable » des fichiers de configuration est apporté avec jinja dans ansible, et complètement dissocié du langage dudit fichier.

      • [^] # Re: Où est l'intérêt ?

        Posté par . Évalué à 2 (+1/-0).

        Et bien justement, générer un fichier de config YAML (ou JSON, même si je pense qu'utiliser JSON pour un fichier de config est une abomination) avec ansible c'est très simple : {{ my_conf_struct | to_nice_yaml(indent=2) }}. On a à la fois un truc simple à générer/automatiser/parser et simple à lire pour le crétin d'humain que je suis (oui parce que parfois, il faut débuguer, et là, il vaut mieux regarder la conf qui est réellement en place, pas celle que l'on pense qui est en place, mais qui est définit dans notre dépôt ansible, dans un autre format par exemple). Toujours en parlant d'ansible, un format à la YAML rend aussi très simple la modif que d'une partie du document, même sans connaître tout le reste.

        • [^] # Re: Où est l'intérêt ?

          Posté par . Évalué à 0 (+0/-1). Dernière modification le 20/05/20 à 15:53.

          Sur la YAML et dans ces colonnes, voir par exemple ce fil, divers points de vue y sont présentés.

        • [^] # Re: Où est l'intérêt ?

          Posté par (page perso) . Évalué à 8 (+6/-1).

          C'est bien chiant le yaml avec ses 42 façons d'écrire la même chose et les pièges de syntaxe…

          Incubez l'excellence sur https://linuxfr.org/board/

          • [^] # Re: Où est l'intérêt ?

            Posté par (page perso) . Évalué à 6 (+3/-0).

            Pourtant, c'est rigolo de traduire la Norvège en "False". En retirant la possibilité de mettre une chaîne de caractère sans les guillemets, ça aurait retiré pas mal de piège.

            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

      • [^] # Re: Où est l'intérêt ?

        Posté par . Évalué à 2 (+0/-0).

        Le côté « programmable » des fichiers de configuration est apporté avec jinja dans ansible, et complètement dissocié du langage dudit fichier.

        Et c'est bien daubé. Ansible utilise jinja, helm utile gotemplate c'est un enfert à lire à écrire, à parser,… Parce que tu as justement 2 langages complètement dissocié. Ils ont un typage différent, ta coloration syntaxique est aux fraises selon les outils que tu utilise,…

        Définir séparément les langages de description et de template pourquoi pas ne pas regarder l'un quand tu utilise l'autre ça amène pas mal de problème. On vit avec, mais ça n'a vraiment pas le goût de « la bonne solution ».

    • [^] # Re: Où est l'intérêt ?

      Posté par . Évalué à 3 (+3/-1).

      J'ai beau avoir lu le journal, je ne comprend absolument pas l'intérêt du truc.

      Programmer la configuration, la valider strictement, la découper en petits morceaux sans crainte que le fusionnement éclatera, etc.

      La syntaxe est tellement peu lisible pour de la config …

      C’est imbibé de la syntaxe des langages comme OCaml et Haskell.

      Et la lisibilité d'une fichier de config est hyper importante aussi.

      Les annotations de types sont là pour augmenter la lisibilité. Le fichier à lire est celui qui est normalisé si on ne veut pas voir les étapes ayant conduit à générer la configuration.

      Bref, je suis partisan du YAML pour la conf (qui est à la fois lisible par un humain, et facilement parsable pour une machine).

      Le YAML n’est ni facile à lire ni à implémenter. Le journal comporte un lien sur une page qui expose succinctement où le bât blesse avec le YAML.

      • [^] # Re: Où est l'intérêt ?

        Posté par . Évalué à 4 (+3/-0).

        Programmer la configuration

        C'est à ça que servent les milliards de moteurs de template et les outils de gestion de conf modernes, Ansible, Salt et tous leurs amis. Là, c'est juste un énième format, plus complexe que les autres.. Et ça augmente la complexité de ces déploiements que la conf soit programmatique, je pensais qu'on s'était enfin débarrassés des .conf.php et leurs équivalents.

        la valider strictement

        Tous les langages de conf pas trop débiles ont des schemas qui les définissent. Problème déjà résolu depuis l'ère des confs en xml.

        Les annotations de types sont là pour augmenter la lisibilité.

        C'est pas idiot d'auto-documenter la conf, mais ça reste quand même un ajout de complexité. M'enfin avoir un type explicite pour ne pas avoir à donner un nom moche comme timeout-milliseconds sur une clé de conf, j'avoue.

        Le YAML n’est ni facile à lire ni à implémenter.

        Et les parseurs YAML que j'ai pu voir ces 10 dernières années sont de la grosse merde en général, incapables de donner des infos aussi fondamentales que à quel ligne/colonne commence cette maudite erreur de syntaxe. Oui, même le parseur yaml de ansible. C'est dommage parce que j'aime bien ce format.
        Séquence hors-sujet : je m'engueulais déjà il y a plus de 10 ans avec un dev d'un de ces premiers parseurs pour lui dire que les messages d'erreur de son parseur étaient inutilisables.

        • [^] # Re: Où est l'intérêt ?

          Posté par . Évalué à 4 (+3/-0).

          Il semble que nous sommes d’accord que le YAML est problématique.

          Maintenant, sur les points où tu objectes, pourrais-tu donner des détails ?

          Tous les langages de conf pas trop débiles ont des schemas qui les définissent. Problème déjà résolu depuis l'ère des confs en xml.

          Les types de Dhall ne sont pas là seulement pour émettre des jugements du genre « on attendait un nombre réel et on en a reçu un. » Ils participent de la fiabilité globale qu’une conf Dhall vous donne. Tu connais certainement des joyeusetés du genre XML entity expansion, sujet largement traité à propos de XML. Regarde ce que ça donne quant au YAML. Les schémas ne protégeront pas de cela à moins de restreindre les fonctionnalités de la norme à implémenter.

          Par conception, une expression Dhall qui a été validée

          • n’induit jamais des erreurs et autres exceptions, donc ne plante jamais ;
          • n’admet jamais des entrées qui se révéleront malformées et n’en donne jamais en sortie ;
          • ne conduira jamais à une boucle infinie. Sur ce point, il y a des cas pathologiques de la famille de la fonction d'Ackermann, mais ici on parle de temps très longs mais finis.

          Les vérificateurs de schémas ne peuvent pas garantir cela, ici également par conception. C’est implicitement de cela dont je voulais évoquer quant à la validité.

          Tout cela peut paraître péremptoire de loin. Sur le site officiel, il y a des explications plus détaillées de beaucoup d’autres choses que ce qu’un journal ou un commentaire peut couvrir. Au fur et à mesure que le côté formel sera exploré, tu verras que la fiabilité de Dhall n’est pas une stratégie de marketing ou quelque chose du genre.

          • [^] # Re: Où est l'intérêt ?

            Posté par . Évalué à 4 (+3/-0).

            Au sujet de la complexité, les formats de fichiers de conf devraient avoir les plus simples possibles, parce que c'est commode de pouvoir les générer automatiquement lors de déploiement automatisés sur un parc de machine. Et lorsqu'un humain regarde le fichier de conf, c'est appréciable que ce soit possible d'en comprendre très rapidement la structure et d'avoir peu de doutes sur sa syntaxe, même s'il ne maîtrise pas l'applicatif. L'idéal est donc de prendre un standard de format de conf texte existant. Or un langage de programmation, c'est l'opposé complet d'un langage textuel simple de fichiers de conf. Ça crée tout de suite un ticket d'entrée plus cher puisqu'il faut comprendre ce nouveau language de conf en plus.
            J'ajouterais que ça n'est pas une solution originale, parce qu'utiliser un language de programmation pour la conf, ça a déjà été testé dans plein de domaines (sites PHP, Chef, …) et que c'est désormais un antipattern notoire. Oui, Configuration As Code, il ne faut pas le prendre littéralement ;-)

            En suite au sujet des bienfaits de Dhall, sur la validation, c'est bien, mais en vrai on s'en fiche dans la plupart des cas. Pour les formats de conf standards, les parseurs pas trop stupides savent déjà éliminer les erreurs syntaxiques, qui sont honnêtement pas celles qui vont arriver en prod le plus souvent. Le cœur du problème, ce qui coûte cher, ce sont les erreurs de format, de type et fonctionnelles, mais je ne vois pas du tout en quoi Dhall aide pour résoudre ce problème. Je pense que Dhall résoud des problèmes qui certes existent, mais avec des confs tellement complexes que leur fonctionnel mérite de s'interroger sur leur pertinence.

            • [^] # Re: Où est l'intérêt ?

              Posté par . Évalué à 1 (+0/-0).

              Sur le fond, il est incertain que je pourrais ajouter quoi que ce soit. Voici donc quelques lignes qui rentrent dans la catégorie « style/goût ».

              • Simplicité (lecture). La forme normalisée de Dhall est tellement simple qu’elle s’explique en une courte phrase : entre {} se trouve un ensemble hétérogène, entre [] un ensemble homogène, le reste constitue des valeurs primitives.

              • Simplicité (programmation). C’est un langage très limité. L’exemple de ce qui est possible sur les Texts est très parlant : on ne peut que les concaténer. L’originalité n’est clamée nulle part car, en fin de compte, on pourrait dire que tous les langages de haut niveau seraient des DSL autour de l’Assembleur qui, soi-même, serait un DSL autour du Code Machine, … :)

              • Pertinence & Apport. Je trouve qu’à chaque fois que la correction, la précision sont augmentées grâce à un outil, ce dernier devrait de facto faire partie des choix possibles dès que ses alternatives imprécises étaient considérées. Mais là, on bifurque dans le normatif et des eaux troubles …

              Donc, dont acte des objections, merci de la conversation.

            • [^] # Re: Où est l'intérêt ?

              Posté par . Évalué à 1 (+0/-1).

              J'ajouterais que ça n'est pas une solution originale, parce qu'utiliser un language de programmation pour la conf, ça a déjà été testé dans plein de domaines (sites PHP, Chef, …) et que c'est désormais un antipattern notoire. Oui, Configuration As Code, il ne faut pas le prendre littéralement ;-)

              Notoire ? Faudra en parler à la plupart des gens qui font de la CI/CD.

              D'ailleurs tu commence par :

              Au sujet de la complexité, les formats de fichiers de conf devraient avoir les plus simples possibles, parce que c'est commode de pouvoir les générer automatiquement lors de déploiement automatisés sur un parc de machine.

              Donc tu montre bien que tu l'a cette complexité. La mettre dans un moteur de template ou dans le fichier de configuration c'est relativement subtile en fin de compte, il y a des arguments pour les 2. D'autant que les moteurs de templates sont généralement bien plus complexes que dahll. Le mettre dans la configuration simplifie drastiquement les déploiements, mais il ne marche pas avec tous les outils, l'utilisation d'un template permet de capitaliser, mais laisse passer des erreurs (si tu as déjà fais des templates yaml tu as déjà eu la contrainte par exemple sur le typage).

              Au lieu d'essayer d'affirmer que ton point de vu est la norme (d'une je suis pas convaincu que ce soit la norme de deux c'est un appel à la population pas forcément intéressant) pourquoi ne pas juste présenter les avantages/inconvénients et ouvrir la discussion plutôt que la fermer ?

              • [^] # Re: Où est l'intérêt ?

                Posté par . Évalué à 3 (+2/-0).

                Notoire ? Faudra en parler à la plupart des gens qui font de la CI/CD.

                Ok, j'ai un peu tiré la définition de cet antipattern. L'explication est qu'on veut que le code soit statique et validé, non modifiable et séparé de la configuration qui elle peut bouger. Si la configuration est dans du code, ça veut dire que toute modification de la configuration peut potentiellement permettre de modifier le reste du code ou d'ajouter du code. Dhall n'est pas un langage de programmation complet et ne rajoutera pas de comportements dans l'appli, donc effectivement mon argument est invalide.

                La CI/CD est par définition du code vu que c'est littéralement du scripting. Qu'est-ce qu'il y a de plus code que exécute ça puis ça et si 1 échoue, alors fait ça ? Suffit de regarder Luminar en bash, Buildbot avec python, Jenkins avec Groovy.

                Donc tu montre bien que tu l'a cette complexité. La mettre dans un moteur de template ou dans le fichier de configuration c'est relativement subtile en fin de compte, il y a des arguments pour les 2. D'autant que les moteurs de templates sont généralement bien plus complexes que dahll. Le mettre dans la configuration simplifie drastiquement les déploiements, mais il ne marche pas avec tous les outils, l'utilisation d'un template permet de capitaliser, mais laisse passer des erreurs (si tu as déjà fais des templates yaml tu as déjà eu la contrainte par exemple sur le typage).

                Malheureusement, on ne choisit pas entre les formats de conf et les moteurs de templates. On a forcément besoin des deux lors des déploiements d'applis. On a forcément besoin de générer ou de valoriser de la conf et quoi de mieux qu'un moteur de templates pour faire ça. Suffit de regarder les templates de cloud init, par exemple, qui regénèrent la conf des VMs à chaque démarrage, qui en sont un bon exemple.
                Donc mon point est que vu qu'on a de toute façon besoin d'un moteur de template pour les déploiements, il vaut mieux que la configuration soit la plus simple possible syntaxiquement afin de faciliter la création des templates et d'éviter de faire des échappements problématiques.

                Ce qui me gène aussi avec Dhall, j'insiste, c'est la complexité. Ils appellent ça un language de configuration, pour moi c'est juste un deuxième moteur de template empilé sur le premier et un deuxième langage de programmation. Ça donne de bonnes choses, comme le système de types et de moins bons, la complexité et la diversité du code qu'on peut faire. Peut-être que c'est un super moteur de templating, avec de géniaux outils de validation et de refactoring, mais ça reste juste un moteur de templating pour faire du json ou du yaml, à moins sans doute d'embarquer une lib. Et si vous dites à vos sysadmins que c'est un meilleur moteur de templating que celui intégré à Ansible, je pense que vous obtiendrez juste un lever de sourcil, et que votre sysadmin adoré (j'adore les miens, en tous cas) retournera à ses scripts ansible et ses templates jinja2.

                J'en reviens à la même question :
                - Quel problème résout cet outil qui n'est pas résolu par des outils ou des process existants, qui marchent déjà ?
                Probablement les soucis de structure et de typage de conf, mais de toute façon, vu qu'on a besoin d'un autre moteur de templating pour le déploiement, ça ne résout pas les problèmes générés par cet autre moteur de templating. Et de toute façon, même si la validation de Dhall dit que tout va bien, ça ne veut pas dire que l'appli va fonctionner avec cette conf, donc ça ne dispense pas de tester en pré-prod ou de faire du A/B testing.

                Ma conclusion serait donc, pourquoi pas l'utiliser si c'est intégré à Ansible et ses amis pour remplacer partiellement jinja2, mais hormis ce cas d'usage, j'ai du mal à voir les bénéfices réels.

                • [^] # Re: Où est l'intérêt ?

                  Posté par . Évalué à 2 (+0/-0).

                  Et de toute façon, même si la validation de Dhall dit que tout va bien, ça ne veut pas dire que l'appli va fonctionner avec cette conf, donc ça ne dispense pas de tester en pré-prod ou de faire du A/B testing.

                  Alors oui, mais c'est pas pour ça que ça n'a pas de valeur. Attraper un problème un problème de conf en CI et l'attraper lors de ton A/B testing n'a pas du tout le même coût. Tu as beau avoir polis ton process autant que tu veux la boucle de feedback n'est pas du tout la même.

                  • [^] # Re: Où est l'intérêt ?

                    Posté par . Évalué à 2 (+1/-0).

                    Oui, mais est-ce que ce gain potentiel vaut tous les coûts que l'ajout de complexité va engendrer ? Je parle de coûts de formation des devs et support, de la complexité ajoutée pour installer les livrables, du coût de convaincre les parties prenantes de la boîte d'avoir une techno de plus qui va mettre des années à remplacer les autres (si ça arrive) et du coût d'être juste 100 pèlerins dans le monde à utiliser cette techno et donc que ce sera compliqué pour avoir du support technique en cas de pépins.

                    • [^] # Re: Où est l'intérêt ?

                      Posté par . Évalué à 3 (+1/-0).

                      Ça c'est autre chose. C'est des choix de techno que tu fais et qui ne sont pas intrinsèque aux techno. Mais reprocher à une techno qui se présente qu'elle n'est connue de personne, c'est dommage. D'autant que c'est un point qui a un minimum était envisagé puisqu'il peut générer du yaml et du json. Ça ne fait pas tout bien sûr. Mais disons que si c'est pour dire que personne connait, on était au courant je pense.

                      • [^] # Re: Où est l'intérêt ?

                        Posté par . Évalué à 1 (+0/-0). Dernière modification le 27/05/20 à 08:23.

                        J'aurais sans doute du en parler dans une autre partie de l'arbre de discussion, parce qu'on est plus dans les mérites techniques, donc hop, je mets la suite dans une autre réponse.

                    • [^] # Re: Où est l'intérêt ?

                      Posté par . Évalué à -1 (+0/-2).

                      damaki :

                      […] coûts de formation […] et support, de la complexité […] de convaincre …

                      Cela est bien entendu plus proche d’un caviardage que d’une citation, mais je le fais pour signaler qu’un glissement vers un biais cognitif ne serait pas éloigné. Le post antérieur a bien caractérisé les choses :

                      barmic :

                      C'est des choix de techno que tu fais. [À propos d’une potentielle migration :] c'est un point qui a un minimum était envisagé puisqu'il peut générer du yaml et du json.

                      Voilà ! Un seul clic sur le site du langage et en promenant la souris au-dessus de la section “Packages”, on se rend compte qu’Ansible & Kubernetes, entre autres, ont une place de choix dans les efforts de promotion. Encore une fois, sur le fond technique, l’échange s’est asséché même si les choses ne sont pas si arides : envisager les coûts d’une migration, certes avec réticence, laisse penser qu’on reconnaît du bon quelque part.

                      Alors, dans le plan de conquête ultime du monde, lorsque l’avant-garde sera en train de ramer, peut-être que des renforts seront envoyés incognito de ta part :) Moins légèrement, quant aux planifications de nature de celle en discussion ici, puisque visiblement ça te tient à cœur, parlons-y : comment y procèdes-tu d’habitude ? À la Geoffrey Moore ? À la John Kotter ? Ou alors à la Clausewitz ?

    • [^] # Re: Où est l'intérêt ?

      Posté par (page perso) . Évalué à 4 (+2/-0).

      Personnellement, je n'aime pas les fichiers de configuration manipulables à la main.
      Pour utiliser Ansible, par exemple, c'est compliqué quand tu veux simplement garantir la présence d'une seule valeur mais sans modifier le reste.

      J'aime bien la solution macOS, avec un format de fichier de config (en vrai, il y a plusieurs représentations possibles, du XML, du binaire, du JSON) qu'on manipule via des outils en ligne de commande ou via des bibliothèques dans chaque langage.
      On peut lire ou modifier n'importe quelle valeur sans se préoccuper du reste du fichier.

    • [^] # Re: Où est l'intérêt ?

      Posté par . Évalué à 4 (+2/-0). Dernière modification le 20/05/20 à 21:17.

      Perso moi c'est l'inverse, je peste dès que je croise un logiciel qui utilise un langage de programmation comme syntaxe de configuration (Ejabberd, Prosody par exemple)
      Ceux en charge du déploiement ne sont pas ceux en charge du développement. Ils n'ont pas besoin de connaître les syntaxes (qui parfois paraissent complètement absurdes) des langages utilisés. Et la lisibilité d'une fichier de config est hyper importante aussi.

      Une opinion qui peut se défendre.

      Bref, je suis partisan du YAML pour la conf (qui est à la fois lisible par un humain, et facilement parsable pour une machine)

      Tu veux dire le langage de fichier de conf qui te chie dans les bottes dès que tu loupes un espace comme en python ? Je préfère largement des fichiers de confs qui utilisent une syntaxe de langage de programmation avec des exemples en commentaire, et qui n'ont pas d'erreurs de syntaxe provoqués par du vide.

      Opera le fait depuis 10 ans.

    • [^] # Re: Où est l'intérêt ?

      Posté par . Évalué à 10 (+10/-0).

      Bref, tu n'y comprends que Dhall.

      • [^] # Re: Où est l'intérêt ?

        Posté par . Évalué à 5 (+3/-0).

        Cette lecture m'a donné la Dhall

        • [^] # Re: Où est l'intérêt ?

          Posté par (page perso) . Évalué à 6 (+3/-0).

          Envie de dal ? Goût pour la goudale ou La goudale ? Un sujet hadal de jeux de mots foireux. Laissons donc le temps des faits au Dhall, que l'on nomme ami, pour voir s'il ment.

          • [^] # Re: Où est l'intérêt ?

            Posté par . Évalué à 3 (+2/-0).

            La personne qui avait la dalle est bien servie, dis donc⁠ !

            L’origine du nom donné au langage est tout aussi facétieuse, voir ici. L’ancêtre du langage est Morte, une appellation encore rigolo⁠ ; Morte a un front-end nommé Annah … et on aura deviné ce qui a inspiré cette appellation !

          • [^] # Re: Où est l'intérêt ?

            Posté par . Évalué à 2 (+1/-0).

            C'est bien connu, les devs qui utilisent des fichiers de configurations qui ne sont pas étanches, on peut dire qu'ils sont porteurs de sandhall.
            Et quand ils jouent à des sports sans filets avec des fichiers de config indisponibles, on peut dire sans hésitation qu'ils sont en mode n/a dhall.
            Ne me cherchez plus, ça fait longtemps que j'ai disparu (---> []), il ne reste que dhall.

  • # Ça me fait un peu penser à Augeas

    Posté par . Évalué à 3 (+1/-0). Dernière modification le 27/05/20 à 00:09.

    Augeas https://augeas.net/ n'a pas type mais a des sortes de schémas qui sont des « lentilles », basées sur des regexp, qui ont en plus une base théorique solide si c'est ton genre de truc. Ça permet de faire de la modification de fichier de configuration avec toute une base de schémas déjà existant pour plein de logiciels qu'on trouve dans /etc. C'est complètement bidirectionnel ce qui est assez génial, et offre une API accessible dans plein de langages pour de la modification programmatique de fichier de configuration.

    Bon, c'est assez différent en fait, car ça n'est pas un truc « générique » comme a l'air d'être le tiens, mais pour gérer de la conf ça semble quand même vachement plus sympa (mon avis).

    • [^] # Re: Ça me fait un peu penser à Augeas

      Posté par . Évalué à 2 (+1/-0).

      « Les choses les plus difficiles en Informatique sont au nombre de deux : vider le cache et identifier les choses.1 »

      Les choses premières en premier, je commence avec l’identification pour noter que le projet est nommé Augeas et est chapeauté par une équipe nommée Hercules ; nul doute que cette équipe s’est à un certain moment proposée de nettoyer les écuries dans les config :) Bref, c’est toujours une agréable surprise de voir des emprunts faits à la mythologie grecque …

      Élégance d’Augeas — l’outil, non pas les écuries, hein2

      Il semble qu’un objet configurable est modélisé en tant que foncteur. Pour des besoins de présentations, j’imagine, le vocabulaire foncteur et consorts est évacué de ce qu’on peut trouver sur le site web officiel. Les auteurs préfèrent parler d’arbre ou graphe. Pour les besoins de ce qui suit, je retiens foncteur.

      La structure sur laquelle est bâtie le reste d’Augeas serait Lens valeur, où Lens est une co-algèbre pour le foncteur Config valeur qui, lui, est une F-algèbre sur les configurables. Prosaïquement, Augeas ferait abstraction des objets configurables de telle façon que, quelle soit ce qu’ils configurent, il serait possible de les manipuler grâce à deux opérations de base, à savoir3

      1. retirer_valeur : config → val, la consultation d’une configuration ;
      2. modifier_valeur : config → val → config, l’actualisation d’une configuration.

      Ces opérations sont applicables à la fois sur un objet en entier ou à ses parties, grâce aux propriétés des Lenses. Et comme on a une algèbre, et ben, des opérations algébriques supplémentaires sont possibles sur ces Lenses.

      Avec un outillage pareil, on peut désormais uniformiser tout ce qui a trait à la configuration, à condition bien sûr de préalablement l’encapsuler sous une Lens. Le bidirectionnel est une conséquence immédiate de l’utilisation des Lenses. Très élégant !

      Et comme des paquets pour nombreuses distributions sont disponibles, j’ai mis la main dans le cambouis.

      # Comment sont traités les processus lancés
      # dans la session en cours si je la ferme ?
      augtool get /files/etc/systemd/logind.conf/Login/KillUserProcesses/value
      # /files/…/value = true

      Au lieu de get, j’aurais pu utiliser un set et cela, indépendamment de la syntaxe réelle qui se trouve dans /etc/systemd/logind.conf (INI dans ce cas-ci mais ça aurait pu être du Bash, du Python, …). En somme, un outil conceptuellement balaise, je dirais. Viennent ensuite les points qui font tache.

      Implémentation d’Augeas

      Le langage à utiliser afin d’ajouter une nouvelle Lens est dérivé de ML, ça promet ! Sauf qu’en jetant un coup-d’œil sur les sources, on voit que Augeas — le ML-like — fait 59.8 % et le C 36.7 %. Le plus du tiers du dépôt en C fait des choses telles du parsing, dommage ! Je pense que ces dernières années, il est devenu inutile d’élaborer sur les méfaits de parser en C.

      Même au-delà du parsing, la manière dont les implémentations alternatives est faite consiste à appeler le C original. Je base cela sur ce qu’on peut par exemple voir pour les bindings en

      • Python : from cffi import FFI …
      • OCaml : external create …
      • Haskell : {-# LANGUAGE CPP, ForeignFunctionInterface #-} …

      Cela étant dit, le projet est là depuis au-moins 2008, sous la houlette de David Lutterkort, employé de Red Hat. Donc, j’imagine qu’il y avait des contraintes corporate à se reposer sur du C pour des tâches pareilles. En plus, le regard qu’on peut porter sur des outils durant cette décennie n’est pas certainement le même qu’il y a deux décennies.

      Un petit détour sur le langage en soi avant de terminer. Ses types primitifs sont unit, string, regexp, lens, tree, et filter. Faire de REGEX un type primitif, même en se limitant à du POSIX étendu, en prenant en plus le soin de contrôler quelles sont les regex qu’on acceptera, ça reste un choix que je qualifierais de hack. Quand on crée un langage de toutes pièces, au lieu d’évacuer un problème (d’expressivité peut-être) dans des regex, autant enrichir la syntaxe du langage qu’on est de toutes façons en train d’inventer.

      En tout cas, merci d’avoir posté sur Augeas, ces satanés travaux d’Héraclès, on finira par les terminer, quelle que soit la configuration !


      1. Traduction libre d’une célèbre citation

      2. Je donne mes impressions en première approximation, je découvre la chose, je commettrai certainement des erreurs qu’une familiarité avec Augeas permettrait d’éviter. 

      3. En reprenant les notations mentionnées dans le journal. 

  • # Le cimetière des nouvelles technos

    Posté par . Évalué à 2 (+1/-0). Dernière modification le 27/05/20 à 08:38.

    Comme toute nouvelle techno, il y a un souci, c'est que personne ne l'utilise et qu'elle n'a pas de communauté pour le support. Malheureusement, quand on utilise une techno en entreprise, on a besoin d'avoir une visibilité sur sa durée de vie, ses corrections de bug. Ici on parle d'une techno pour les confs, élément critique par excellence et c'est donc extrêmement compliqué d'utiliser une techno sortie du chapeau pour ce besoin, malgré toutes les belles choses qu'elle peut apporter et même si c'est juste un générateur. L'excellence technique ne suffit pas, il faut une perception de garantie de présence dans l'industrie et de pérennité. J'ai malheureusement plein de technos orphelines dans les placards (dbdeploy et Jelix, petits anges partis trop tôt). Et malheureusement, c'est rare que les entreprises prennent l'initiative de la forker en open source et de prendre le relai de la maintenance.

    • [^] # Re: Le cimetière des nouvelles technos

      Posté par . Évalué à 2 (+0/-0).

      Tous les logiciels n'ont pas les même contraintes. Il y en a un paquet qui ont une configuration très spécifique. Si on omet vim&emacs qui utilisent leur propre langage pour se configurer tu peux trouver des logiciels comme awesome qui utilise lua ou i3 qui a un format bien à lui.

      En tant que lead tech plus intéressant que de savoir s'il faut remplacer tout ce que tu as avec ça, ce qui me semble plus intéressant c'est :

      • de comprendre l'intérêt/la philosophie/l'objectif pour envisager comment est-ce que c'est actuellement pris en compte (ou non) dans ton quotidien. S'intéresser est toujours plus enrichissant que de démonter
      • avoir potentiellement une nouvelle techno si un jour le besoin se fait sentir

      Après tu aura tous pleins de cabinets de conseil qui te sortiront des graphe de techno classées comme "expérimentale", "bleeding edge", "stable" et "deprecated". C'est à mon avis plus intéressant de regarder ce qui se fait et d'avoir son propre avis.

      Tiens c'est marrant il y a un super fonctionnalité : il peut générer un sha256 de la configuration, mais il le fait sur la sémantique de la configuration et pas sur le fichier. Ça peut être super utile.

      Après il y a effectivement la confiance que tu fais en vers les développeurs de dhall, c'est à toi de voir de la même manière que tu fait confiance à d'autres projets. Il n'y a pas que la pérennité qui soit importante. Pour m'avoir fait sauter ma configuration dans une version micro je suis méfiant d'haproxy par exemple.

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.