Un gestionnaire de dotfiles devient légitime dès lors que l’on jongle entre différents environnements.
Chezmoi est un gestionnaire de dotfiles puissant et simple d’accès.
Son usage est décuplé dès lors que les conteneurs entrent dans l’équation.
En ces temps de confinement au domicile, le temps pour soi redevient possible.
On se voit à reprendre notre TODO list personnelle pour y dépiler les tâches.
En ce qui me concerne, autour de la 121ème place se trouvait le besoin d’industrialiser la gestion de mes dotfiles.
Ces fichiers tel le .bashrc, le .gitconfig et autres .vimrc qui permettent de piloter la manière dont nous interagissons avec notre environnement et les outils qu’il embarque.
Mais quelle est la pertinence d’industrialiser la gestion de tels fichiers ?Effectivement, ce besoin est artificiel si vous avez l’habitude de travailler sur une unique machine.
Cette situation a été la mienne durant ces 5 dernières années.
Pour cette raison je ne m’étais jamais réellement penché sur le sujet.
Maintenant prenons une situation plus réaliste dans laquelle nous avons une machine professionnelle et une personnelle.Ma machine personnelle est configurée aux petits oignons. Mais arrivé sur le terminal de mon poste de travail, entrer alias_de_la_mort_qui_tue
me renvoie command not found
. Pénible.
Il nous faut de la cohérence entre les dotfiles de ces deux machines pour être efficace et se sentir “comme à la maison” quel que soit l’environnement.
Je vais amplifier ce besoin avec la remarque suivante :
Nous parlons de deux machines, mais aujourd’hui la réalité se rapproche plus d’une infinité de machines, ou plus précisément, une infinité d’environnements.
Est ce que la technologie des conteneurs vous parle ?
Assez récemment, en tant que développeur cloud native, je n’avais qu’un usage direct limité de cette technologie.
Après tout, charge à des services tel K8S, lambda function ou un dyno Heroku de gérer les conteneurs.
Il m’était beaucoup plus facile de gérer le multi environnement avec des outils type virtualenv (dans le cas de Python) plutôt que de les gérer via Docker que je voyais comme un outils Ops.
C’était sans compter cette merveilleuse extension VSCode qui simplifie grandement l’usage de Docker pour un développeur, concurrençant sérieusement virtualenv, bundler et consort.
Comment donc assurer la cohérence et la gestion de ces environnements?
La duplication par copier-coller fonctionne… d’accord. Mais comment allez-vous gérer la divergence des dotfiles sur ces différentes machines?
Le problème est sans fin et clairement ne passe pas à l’échelle.
Git arrive à la rescousse. Cette solution simple se base sur un dépôt Git en tant que point de vérité unique vis à vis du contenu de ces dotfiles.
Il s’agirait donc de renseigner ces dotfiles dans un dépôt à cloner sur chacun des environnements et de créer des liens symboliques au bon endroit via un script (power)shell.
Le clonage du dépôt peut être envisagé de manière automatique si l’environnement est éphémère.
Il existe cependant deux objections à cette approche :
Le premier point peut trouver un élément de réponse à travers le système de branches Git.
Nous créerions alors une branche par environnement pour ensuite tirer la branche voulue depuis un environnement.
Methode simple… mais non efficace.
Comment dès lors gérer simplement les nombreuses branches potentielles dont le nombre peut égaler celui des environnements cibles ?
Comment automatiquement déterminer si un environnement doit tirer telle ou telle branche ?
Ce couplage fort entre environnement et branche git est un problème. Un système intéressant serait de “faire dire” à l'environnement quelle version du fichier de configuration l’intéresse. Pour ceux connaissant les applications 12 factors, le factor III appelle un environnement à porter la configuration d’un applicatif et non pas l’applicatif lui-même.
Par extension, en remplaçant “applicatif” par “source de vérité”, il faudrait que cette dernière soit la même sur tous les environnements mais que son “expression” diffère en fonction de l'environnement hôte.
Soit par son type, le contenu d’un fichier spécifique, la présence de variables d’environnements, d’un nom de host, etc
De cette manière nous aurions un dépôt avec une branche unique dans laquelle nos dotfiles seraient des templates dont la sortie dépendra de l’environnement dans lequel on le clone.
Le second point doit être délégué à un outil spécialisé tel que pass, lastpass ou encore Vault.
En d’autres termes, le gestionnaire de dotfiles doit “comprendre” ces outils.
Si l’on résume, notre outil de management de .dotfiles aurait dans l’idéal :
Enfin, j’ajouterais la facilité d’installation avec un minimum de requis pour le système hôte.
Exit les obligations de runtime ou autres JVM. Un exécutable binaire par exemple.
Après avoir testé plusieurs solutions mon choix s’est arrêté sur Chezmoi.
Cet outil a le bon goût de répondre élégamment aux trois critères précédemment énoncés et va même au-delà.
En définissant un “état source” (le point de vérité) à travers un répertoire contenant des dotfiles templatisés, Chezmoi va être capable de définir un état cible dans un environnement, cet état dépendant d’un fichier de configuration propre à l’environnement.
Chezmoi offre des facilités pour initialiser ce fichier à partir d’un template.
Rq : Nous pouvons comparer ce fichier de configuration Chezmoi au fichier .env de dotenv.
Voici ce que l’on peut retenir de Chezmoi :
Les capacités de l’outil ne s’arrêtent pas là et je vous invite à lire cette section du repository Github.
Note : Dans l’absolu, Chezmoi peut servir de point de vérité pour l’état de n’importe quel fichier/répertoire. Ce n’est néanmoins pas l’esprit de l’outil qui déléguera ce genre de responsabilité à des outils plus riches tels Ansible, Puppet, ...
Les deux schémas suivant résument les principes de Chezmoi :
Sont entourés en vert les deux répertoires qui se répondent par l’intermédiaire de Chezmoi et présents sur chaque environnement.
Note 1 : Env1 et Env2 résident en pratique sur deux machines différentes.
Note 2 : Notez la ressemblance du flow git (push + pull) avec celui de Chezmoi (apply + add).
Enfin, la meilleure solution n’est rien sans communauté ni documentation.
Chezmoi est utilisé par une communauté assez large et dispose d’une documentation claire et précise.
Pour information, l’auteur de la solution a suivi les recommandations de ce billet de blog.
Nous avons précédemment parlé de VSCode ainsi que sa remote Containers extension.
En quoi Chezmoi va améliorer cette association?
Prenons donc la situation suivante.
En tant que développeur, nous avons un side project en Go, un projet professionnel en Java et projet associatif Php.
Ces différents projets sont portés par trois conteneurs Docker différents sur lesquels nous développons grâce à l’extension VSCode. Chacun portant ses dépendances propres.
Enfin, n’oublions pas le système hôte qui aura aussi besoin de nos dotfiles.
Nous souhaitons avoir un état cible de nos dotfiles, différents pour chaque environnement.
C’est là que Chezmoi intervient.
En supposant que c’est la première fois que nous utilisons Chezmoi, voici une proposition d’étapes à suivre pour y arriver.
Nous commençons par créer notre état source (le dépôt Git distant) sur notre environnement hôte.
Chezmoi add [target]
ajoutera un dotfile représenté par la target au répertoire source en tant qu’attribute Chezmoi.Chezmoi data
.-T --autotemplate
, pour que l’attribute généré soit templatisé en fonction du contenu du fichier de configuration.id=”foo@bar.com”
Mon fichier de config : [data]email=”foo@bar.com”
Alors le template généré par chezmoi add -T --autotemplate dotfile
contiendra :id=
Le matching étant fait par la valeur et non la clé.[data]category=”professional”
chezmoi apply
:
Anything you want
Other thing you want
apply
est la commande permettant de transformer le contenu du répertoire source en contenu pour le répertoire cible.A la fin de ces étapes, nous sommes donc avec un dépôt Github qui peut ressembler à celui-ci ou celui-là.
Nous voulons désormais démarrer des environnements dockerisés via VSCode avec des dotfiles adaptés.
L’idée va être de s’appuyer d’une part sur l’état source que nous venons de créer, et d'automatiser l’installation de Chezmoi et la génération des dotfiles dans un conteneur d’autre part.
Le code source de cette approche se trouve ici.
Nous nous appuyons sur son contenu pour illustrer les étapes.
Et voilà!
Vous pouvez désormais oublier ces étapes. Chaque redémarrage du conteneur vous ouvrira un environnement avec les dotfiles adaptés.
Il suffit de reproduire ces étapes sur d’autres conteneurs pour atteindre la cible que nous nous étions fixée.
Pour aller plus loin, nous pouvons remarquer que le contenu de la source de vérité peut être “proxifié” à travers un volume Docker.
Il suffit de copier le contenu d’un répertoire source existant dans un volume créé pour l’occasion (par exemple avec un docker cp du repo git local vers ce volume monté sur une busybox).
Dès lors, chaque conteneur sur lequel est attaché ce volume bénéficiera en temps réel des changements et ajouts apportés par tel ou tel environnement bénéficiant de l’installation précédente.
Le tout sans avoir besoin d'une connexion à internet.
Rq : Le volume est à monter sur le chemin du répertoire source par défaut : ~/.local/share/chezmoi
Il est à noter qu’il n’est plus nécessaire de cloner un répertoire source au niveau du conteneur. Le volume mount défini dans le docker-compose file remplace cette étape.
Nous créons alors la nouvelle notion de volume source et pourquoi pas de bucket source avec les bons drivers.
Le schéma ci-dessous illustre l’idée qui dans les faits fonctionne très bien :
En conclusion
Chezmoi est un outil simple et puissant.
Les quelques commandes et cas d’usage mis en avant ne font que gratter la surface de ce que permet Chezmoi.
Chezmoi.io illustre de belle manière les différents cas d’usage.
Au vu de l’intégration que nous en faisons avec les conteneurs, il apparaît qu’une évolution intéressante serait de définir les variables de template directement par les variables d’environnement plutôt qu’un fichier de configuration. Variables dont les valeurs seraient portées par le Docker-compose file.
La suggestion a été soumise, approuvée et implémentée dans le dépôt officiel de Chezmoi rappelant qu'il est facile d'y contribuer.
Sur ce, je vous souhaite la bienvenue Chezmoi.