Ansible -Contrôler vos playbooks avec Ansible-Lint
Publié le : 4 octobre 2021 | Mis à jour le : 4 mai 2023Table des matières
Lorsqu’on écrit des playbooks et des rôles Ansible, comme pour tous les langages de programmation, il y a un certain nombre de bonnes pratiques et de règles à respecter pour obtenir un code de qualité. A moins de faire toujours la même chose, il est difficile de connaître toutes ces règles. C’est là qu’interviennent les outils de linting. Ansible-Lint va vous permettre de contrôler le respect de toutes ces règles et d’éviter les pièges courants sur vos playbooks, vos rôles et même les collections. Ansible-lint va également vous aider à mettre à niveau votre code pour qu’il continue de fonctionner lors des sorties des nouvelles versions d’Ansible.
Le projet Ansible Galaxy utilise Ansible-Lint pour calculer les scores de qualité des codes déposés dans le Galaxy Hub.
Installation d’Ansible Lint
Comme Ansible, l’outil ansible-lint est écrit en python, et donc son installation se fait via pip.
On va l’installer avec yamllint
.
pip3 install "ansible-lint[yamllint]"
Dans le cas où vous utilisez encore d’anciennes versions d’Ansible, il est possible de choisir une version du linter compatible avec celle-ci.
pip3 install ansible-lint "ansible>=2.9,<2.10"
Que contrôle ansible lint?
Par défaut cet outil permet de contrôler en autre :
- l’utilisation
command
oushell
plutôt qu’un module existant prenant en charge cette commande - l’utilisation
command
plutôt queshell
(si le module équivalent n’existe pas) - le bon respect des espaces dans les noms de variables : {{ my_variable }} et non {{my_variable}}
- la présence de
local_action
qui doit être remplacé pardelegate_to: localhost
- l’utilisation de modules dépréciés
- les tests de chaînes de caractères de longueur nulle: when:
var|length > 0
- l’utilisation du nom complet pour les modules
ansible.builtin
(depuis la version 3.0 d’ansible) - l’utilisation de
failed_when
avec ses conditions d’erreurs plutôt queignore_errors
- l’utilisation des FQCN : Full Qualified Collection Names
- …
La liste complète avec leurs explications
Pour afficher toutes les règles utilisées par défaut, il suffit de taper la commande suivante :
ansible-lint -v -T
INFO Identified / as project root due file system root.
# List of tags and rules they cover
command-shell: # Specific to use of command and shell modules
- command-instead-of-module
- command-instead-of-shell
- inline-env-var
- no-changed-when
- risky-shell-pipe
core: # Related to internal implementation of the linter
- internal-error
- load-failure
- parser-error
- syntax-check
- warning
- schema
Pour limiter les tests sur certaines règles, il suffit d’utiliser l’option -t
.
Par exemple pour lancer un contrôle sur juste l’idempotence :
ansible-lint -t idempotency playbook.yml
De la même manière pour exclure certaines règles :
ansible-lint -x formatting,metadata playbook.yml
On peut plutôt que de les ignorer les afficher en warning:
ansible-lint -w experimental playbook.yml
Ansible-Lint par la pratique
Prenons ce playbook par exemple :
---
- hosts: all
gather_facts: no
tasks:
- name: this would typically fire deprecated-command-syntax
command:
cmd: chmod 644 X
- name: this would typically fire command-instead-of-module
command: git pull --rebase
- name: this would typically fire git-latest
git:
repo: http://git.com/test
dest: /tmp/test
qui retourne :
WARNING Listing 12 violation(s) that are fatal
name[play]: All plays should be named.
test.yaml:2
yaml[truthy]: Truthy value should be one of [false, true]
test.yaml:3
fqcn[action-core]: Use FQCN for builtin module actions (command).
test.yaml:6 Use `ansible.builtin.command` or `ansible.legacy.command` instead.
name[casing]: All names should start with an uppercase letter.
test.yaml:6 Task/Handler: this would typically fire deprecated-command-syntax
no-changed-when: Commands should not change things if nothing needs doing.
test.yaml:6 Task/Handler: this would typically fire deprecated-command-syntax
command-instead-of-module: git used in place of git module
test.yaml:10 Task/Handler: this would typically fire command-instead-of-module
fqcn[action-core]: Use FQCN for builtin module actions (command).
test.yaml:10 Use `ansible.builtin.command` or `ansible.legacy.command` instead.
name[casing]: All names should start with an uppercase letter.
test.yaml:10 Task/Handler: this would typically fire command-instead-of-module
no-changed-when: Commands should not change things if nothing needs doing.
test.yaml:10 Task/Handler: this would typically fire command-instead-of-module
fqcn[action-core]: Use FQCN for builtin module actions (git).
test.yaml:13 Use `ansible.builtin.git` or `ansible.legacy.git` instead.
latest[git]: Result of the command may vary on subsequent runs.
test.yaml:13 Task/Handler: this would typically fire git-latest
name[casing]: All names should start with an uppercase letter.
test.yaml:13 Task/Handler: this would typically fire git-latest
Read documentation for instructions on how to ignore specific rule violations.
Rule Violation Summary
count tag profile rule associated tags
1 command-instead-of-module basic command-shell, idiom
1 name[play] basic idiom
1 yaml[truthy] basic formatting, yaml
3 name[casing] moderate idiom
1 latest[git] safety idempotency
2 no-changed-when shared command-shell, idempotency
3 fqcn[action-core] production formatting
Failed after min profile: 12 failure(s), 0 warning(s) on 1 files.
Que faut-il faire pour qu’ansible-lint ne retourne pas d’erreurs ?
- Mettre des majuscules à la première lettre de la description
- Ajouter à la ligne 2
name: UMn playbook
- A la ligne 3 remplacer
no
parfalse
- A la ligne 9 on doit ajouter
changed_when
pour indiquer à Ansible quand la commande utilisée va réellement changer quelque chose sur votre machine cible. - A la ligne 10 remplacer le module git par son propre module !!!
- Pour que l’on respecte les règles d’idempotence, il est important de ne pas
utiliser
default
mais de nommer une version explicite.
Si on souhaite forcer certaines règles, il est possible d’ajouter des arguments au playbook :
- name: this would typically fire git-latest
git:
repo: http://git.com/test
dest: /tmp/test
args:
warn_list: false
- Pour les autres modules, on peut skipper le test en ajoutant le tag
skip_ansible_lint
:
- name: this would typically fire git-latest
git:
repo: http://git.com/test
dest: /tmp/test
tags:
- skip_ansible_lint
On peut, comme l’indique la commande, créer un fichier .ansible-lint
contenant
par exemple :
# .ansible-lint
warn_list: # or 'skip_list' to silence them completely
- yaml # Violations reported by yamllint
Mais je n’aime pas trop cela, car dans ce cas ce sont toutes les erreurs de ce type qui sont ignorées.
Ansible-lint apporte certaines corrections tout seul
Introduit avec la version 6.0.0
, ansible-lint permet désormais d’apporter certaines corrections à votre place avec l’option --write
:
- L’utilisation des FQCN : fqcn
- La première lettre de la description en capitale : name
- les valeurs booléenes à
true
oufalse
: yaml
Cette option s’enrichit au fil de la sortie des versions.
Utilisation de l’option –write
Cette option prend une valeur qui peut être all
, none
ou une liste des id de règles à corriger séparés par des virgules.
Si on reprend notre fichier exemple ci-dessus et que nous voulons corriger la capitalisation :
ansible-lint --write none,name test.yaml
Cela nous donne ce résultat :
---
- hosts: all
gather_facts: false
tasks:
- name: This would typically fire deprecated-command-syntax
command:
cmd: chmod 644 X
- name: This would typically fire command-instead-of-module
command: git pull --rebase
- name: This would typically fire git-latest
git:
repo: http://git.com/test
dest: /tmp/test
ansible-lint --write all test.yaml
---
- hosts: all
gather_facts: false
tasks:
- name: This would typically fire deprecated-command-syntax
ansible.builtin.command:
cmd: chmod 644 X
- name: This would typically fire command-instead-of-module
ansible.builtin.command: git pull --rebase
- name: This would typically fire git-latest
ansible.builtin.git:
repo: http://git.com/test
dest: /tmp/test
ansible-lint
a corrigé les fqcn manquants !!!
Écrire ses propres règles Ansible-Lint
Il est possible de créer ses propres règles et de les utiliser avec l’option -r /path/to/custom-rules
.
Pour la syntaxe des règles il suffit de se rendre sur cette page : custom-rules
Si on veut les utiliser conjointement avec les règles par défaut, on remplace
-w
par -W
.
La suite
Il ne vous reste plus qu’à l’intégrer à votre ci !!
Si vous voulez plus de tutorials Ansible je vous renvoie sur le billet de l'introduction à ansible
Deux alternatives ansible-later et spotter, qui est celui qui donne le plus de recommendations sur l’amélioration de votre code Ansible.