Introduction
It’s always good to learn something new. But doing it the right way from the very beginning is even better.
I recently started to work with Ansible and after creating a few roles, I quickly realized that there were many different ways to achieve the same goal.
Some examples are :
– The use of the Shell module vs the Command module
– The use of Loop vs With_*
– The use of an Handler vs a Task when it comes to run operations on change
On one side, having such liberty is pretty fun, as it leaves room for everyone’s imagination. But on the other, having some best practices or guidelines can also become very important, especially when working in a shared development environment (using git for example) and when you want to guarantee code uniformity.
In the Ansible world, Ansible Lint is the tool to start with when you want to check your Playbooks and Roles code under various aspects.
Its goal is also to help developpers to write their code in a way that it remain compatible with newer versions of Ansible. To achive this Ansible Lint will, for instance, check the use of deprecated modules or commands.
Installation
apt install ansible-lint
pip3 install ansible-lint
joc@jocbox:~$ ansible-lint --version ansible-lint 5.0.7.dev3 using ansible 2.9.6 joc@jocbox:~$
Default rules
By default, Ansible Lint will run based on a set of default rules. The complete list can be found in the official documentation : https://ansible-lint.readthedocs.io/en/latest/default_rules.html
You can also use the command ansible-lint -L to list them directly in your console :

You can also run it directly against a specific role :
joc@jocbox:/ansible$ ansible-lint roles/ora_rdbms_getmospatch/* WARNING Listing 1 violation(s) that are fatal deprecated-local-action: Do not use 'local_action', use 'delegate_to: localhost' roles/ora_rdbms_getmospatch/tasks/combo.yml:39 local_action: joc@jocbox:/ansible$ ansible-lint roles/ora_rdbms_getmospatch/*
The output above is quite clear : The keyword local_action is deprecated and delegate_to must be used instead. This is one of the Ansible Lint default rules.
Unfortunately, in that case the delegation is done on a per-task basis (see below), thus I have no other choice to use local_action. We can consider this Warning as a false positive.
Skipping a rule
joc@jocbox:~/ansible$ cat .ansible-lint skip_list: - deprecated-local-action joc@jocbox:~/ansible$
joc@jocbox:/ansible$ ansible-lint roles/ora_rdbms_getmospatch/* -x deprecated-local-action joc@jocbox:/ansible$
Hopefully, if the rule is line-based, you can disable it for a single task by placing # noqa [rule_id] at the end of the particular line you want to be skipped :
- name: Copy combo patch to repository become: true become_user: ansible local_action: # noqa deprecated-local-action module: ansible.builtin.copy src: "{{ rv_ora_rdbms_getmospatch_tmp_folder }}/{{ pv_ora_patch_list.combo[combo_patch_id].patch_archive | basename }}" dest: "{{ pv_ora_patch_list.combo[combo_patch_id].patch_archive }}" owner: ansible group: ansible loop: "{{ pv_ora_patch_list.combo | list }}" loop_control: loop_var: combo_patch_id label: "{{ combo_patch_id }} - {{ pv_ora_patch_list.combo[combo_patch_id].desc }}"
- name: Copy combo patch to repository become: true become_user: ansible local_action: # noqa deprecated-local-action module: ansible.builtin.copy src: "{{ rv_ora_rdbms_getmospatch_tmp_folder }}/{{ pv_ora_patch_list.combo[combo_patch_id].patch_archive | basename }}" dest: "{{ pv_ora_patch_list.combo[combo_patch_id].patch_archive }}" owner: ansible group: ansible loop: "{{ pv_ora_patch_list.combo | list }}" loop_control: loop_var: combo_patch_id label: "{{ combo_patch_id }} - {{ pv_ora_patch_list.combo[combo_patch_id].desc }}" tags: - skip_ansible_lint
Integration with pre-commit
To do that, just update your local .pre-commit-config.yaml file with the following :
joc@jocbox:~/ansible$ cat .pre-commit-config.yaml repos: - repo: https://github.com/ansible-community/ansible-lint.git rev: v5.1.3 hooks: - id: ansible-lint files: \.(yaml|yml)$ joc@jocbox:~/ansible$