Aller au contenu
Infrastructure as Code medium

Ansible-lint : valider et améliorer votre code Ansible

12 min de lecture

logo ansible

Ansible-lint analyse vos playbooks, rôles et collections pour détecter les erreurs avant l’exécution, appliquer les bonnes pratiques et corriger automatiquement de nombreux problèmes. C’est l’outil indispensable pour maintenir un code Ansible de qualité, utilisé notamment par Ansible Galaxy pour calculer les scores de qualité.

Fenêtre de terminal
pipx install ansible-lint
ansible-lint --version

Avantage : environnement isolé, indépendant de votre version d’Ansible.

Fenêtre de terminal
# Lancer sur un playbook
ansible-lint playbook.yml
# Lancer sur tout le projet (auto-détection)
ansible-lint
# Corriger automatiquement ce qui peut l'être
ansible-lint --fix

Ce qu’Ansible-lint détecte (et ce qu’il ne fait pas)

Section intitulée « Ce qu’Ansible-lint détecte (et ce qu’il ne fait pas) »
Ansible-lint faitAnsible-lint ne fait pas
Détecte les erreurs de syntaxeN’exécute pas les playbooks
Applique les bonnes pratiquesNe remplace pas les tests d’intégration
Corrige automatiquement (—fix)Ne corrige pas les erreurs de logique
Valide les schémas (meta, galaxy.yml)Ne vérifie pas les cibles distantes

Les profils permettent une adoption progressive : commencez permissif, durcissez au fil du temps. Chaque profil inclut les règles du profil précédent.

ProfilObjectifQuand l’utiliser
minAnsible peut charger le fichierDébogage, code legacy
basicStyle cohérent, erreurs courantesDébut de projet
moderateLisibilité (noms, casing)Équipe établie
safetySécurité et idempotencePré-production
sharedPrêt pour Galaxy/publicationRôles/collections publics
productionCertifié Ansible Automation PlatformEntreprise
Fenêtre de terminal
# Voir tous les profils et leurs règles
ansible-lint --list-profiles
# Appliquer un profil spécifique
ansible-lint --profile=basic playbook.yml
# Vérifier quel profil passe
ansible-lint playbook.yml
# Sortie : "Last profile that met the validation criteria was 'safety'"

Créez un fichier .ansible-lint à la racine de votre projet :

.ansible-lint
---
profile: moderate
# Exclure des chemins
exclude_paths:
- .cache/
- .git/
- molecule/
# Ignorer certaines règles
skip_list:
- no-changed-when # Trop de faux positifs sur nos scripts
# Afficher en warning au lieu d'erreur
warn_list:
- experimental
- fqcn[deep]
# Activer des règles opt-in
enable_list:
- yaml
- no-log-password
- empty-string-compare
# Mode hors ligne (pas de téléchargement de requirements.yml)
offline: false
# Pattern pour les noms de variables
var_naming_pattern: "^[a-z_][a-z0-9_]*$"
# Préfixe pour les variables de boucle dans les rôles
loop_var_prefix: "^(__|{role}_)"

L’option --fix corrige automatiquement de nombreuses erreurs. C’est la fonctionnalité la plus utile pour gagner du temps.

RègleCe qui est corrigé
fqcncommand:ansible.builtin.command:
namethis taskThis task (majuscule)
yamlFormatage YAML (indentation, espaces)
no-free-formSyntaxe libre → syntaxe structurée
key-orderRéordonne les clés selon la convention
jinja{{var}}{{ var }} (espaces)
no-jinja-whenwhen: "{{ }}"when: sans Jinja
partial-becomeAjoute become: true manquant
Fenêtre de terminal
# Corriger tout le projet
ansible-lint --fix
# Corriger uniquement les FQCN
ansible-lint --fix=fqcn
# Corriger plusieurs règles spécifiques
ansible-lint --fix=fqcn,name,yaml
# Ne rien corriger (désactiver les transforms)
ansible-lint --fix=none

Avant correction :

---
- hosts: all
gather_facts: no
tasks:
- name: install package
apt:
name: nginx
state: present

Après ansible-lint --fix :

---
- hosts: all
gather_facts: false
tasks:
- name: Install package
ansible.builtin.apt:
name: nginx
state: present

Corrections appliquées :

  • nofalse (yaml[truthy])
  • installInstall (name[casing])
  • apt:ansible.builtin.apt: (fqcn)
- name: Clone repository without using git module # noqa: command-instead-of-module
ansible.builtin.command: git clone https://example.com/repo
changed_when: false
# Ignorer plusieurs règles
- name: Risky but necessary # noqa: risky-shell-pipe no-changed-when
ansible.builtin.shell: cat /etc/passwd | grep root

Méthode 2 : fichier .ansible-lint-ignore (pour un fichier)

Section intitulée « Méthode 2 : fichier .ansible-lint-ignore (pour un fichier) »
Fenêtre de terminal
# Générer automatiquement le fichier d'ignore
ansible-lint --generate-ignore

Contenu généré :

.ansible-lint-ignore
playbook-legacy.yml command-instead-of-module
playbook-legacy.yml fqcn[action-core]
playbook-legacy.yml no-changed-when
- name: Task à ignorer complètement
ansible.builtin.git:
repo: https://example.com/repo
dest: /tmp/repo
tags:
- skip_ansible_lint
.pre-commit-config.yaml
---
repos:
- repo: https://github.com/ansible/ansible-lint
rev: v26.1.1
hooks:
- id: ansible-lint
# Si vous utilisez des collections externes :
# additional_dependencies:
# - ansible
Fenêtre de terminal
# Installer pre-commit
pip install pre-commit
pre-commit install
# Exécuter manuellement
pre-commit run ansible-lint --all-files
.github/workflows/lint.yml
name: Ansible Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Run ansible-lint
uses: ansible/ansible-lint@main
# with:
# args: "--profile=production"
.gitlab-ci.yml
ansible-lint:
image: python:3.12-slim
stage: lint
before_script:
- pip install ansible-lint
script:
- ansible-lint --profile=moderate
rules:
- changes:
- "**/*.yml"
- "**/*.yaml"

Pour des besoins spécifiques à votre organisation, créez des règles personnalisées :

rules/no_hardcoded_passwords.py
from ansiblelint.rules import AnsibleLintRule
class NoHardcodedPasswords(AnsibleLintRule):
id = "custom-no-passwords"
shortdesc = "Ne pas hardcoder de mots de passe"
description = "Les mots de passe doivent venir de variables ou vault"
tags = ["security", "custom"]
def matchtask(self, task, file=None):
for key in ["password", "passwd", "secret"]:
if key in str(task.get("ansible.builtin.user", {})):
value = task["ansible.builtin.user"].get(key, "")
if not value.startswith("{{"):
return True
return False
Fenêtre de terminal
# Utiliser avec les règles par défaut
ansible-lint -R -r ./rules/
# Utiliser uniquement vos règles
ansible-lint -r ./rules/
ProblèmeCause probableSolution
No such file or directoryChemin invalideLancer depuis la racine du projet
Syntax check failedErreur YAMLCorriger la syntaxe avec yamllint
Unable to resolve FQCNCollection manquanteInstaller avec ansible-galaxy collection install
Too many violationsProjet legacyUtiliser --generate-ignore pour démarrer
Pre-commit échoueCollections non trouvéesAjouter additional_dependencies: [ansible]
Faux positifs sur no-changed-whenCommands idempotentesAjouter # noqa: no-changed-when avec commentaire
Fenêtre de terminal
# Toutes les règles
ansible-lint --list-rules
# Toutes les règles avec leurs tags
ansible-lint -T
# Uniquement certains tags
ansible-lint -t idempotency playbook.yml
ansible-lint -t security playbook.yml
# Exclure certains tags
ansible-lint -x formatting,metadata playbook.yml
  1. ansible-lint --fix corrige automatiquement FQCN, casing, YAML et autres problèmes — utilisez-le systématiquement
  2. 6 profils de min à production — commencez avec basic, montez progressivement
  3. .ansible-lint centralise la configuration — committez ce fichier
  4. # noqa: rule-id ignore une règle sur une ligne — préférez cette syntaxe à skip_list
  5. --generate-ignore génère un fichier d’ignore pour le code legacy — permet l’adoption progressive
  6. Intégrez en CI/CD avec pre-commit ou GitHub Actions — détectez les erreurs avant le merge
  7. Le code de sortie 8 (v26+) indique que des corrections ont été appliquées avec succès
  8. Exécutez toujours depuis la racine du projet, sinon ansible-lint ne trouvera pas les fichiers

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn