ansible-lint is a tool to check Ansible Playbook.
ansible-community / ansible-lint
Best practices checker for Ansible
Ansible-lint
ansible-lint
checks playbooks for practices and behaviour that could
potentially be improved. As a community backed project ansible-lint supports
only the last two major versions of Ansible.
Visit the Ansible Lint docs site
Contributing
Please read Contribution guidelines if you wish to contribute.
Licensing
The code in the ansible-lint repository is licensed under the MIT license. If you contribute to this repository, that license applies to your contributions.
The ansible-lint project also imports the Ansible python module, which is licensed under the GPLv3 license. Because of this import, the GPLv3 rules apply to the full distribution of ansible-lint. We maintain the MIT license on the repository so we can fully use an MIT license in the future if we ever remove the runtime dependency on Ansible code.
Installing the ansible-lint python package does not install any GPL dependencies, all of them are listed as extras.
Authors
ansible-lint was created…
It helps you to find syntax problems like extra spaces or lines, or point out where doesn't follow Ansible best practice.
[koh@kohs-MBP] ~/work/linttest
% ansible-lint site.yml
[201] Trailing whitespace
site.yml:6
msg: hello
[403] Package installs should not use latest
site.yml:8
Task/Handler: install httpd
[koh@kohs-MBP] ~/work/linttest
%
Below is the list of default rules.
https://docs.ansible.com/ansible-lint/rules/default_rules.html
But each playbook or teams might have their own rules that oppose to Ansible best practice.
Here is how to configure ansible-lint.
*Version of ansible-lint is 4.1.0
.
Config with command line options
Rules are configurable with options of ansible-lint command.
[koh@kohs-MBP] ~/work/linttest
% ansible-lint --help
Usage: ansible-lint [options] playbook.yml [playbook2 ...]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-L list all the rules
-q quieter, although not silent output
-p parseable output in the format of pep8
--parseable-severity parseable output including severity of rule
-r RULESDIR specify one or more rules directories using one or
more -r arguments. Any -r flags override the default
rules in
/Users/koh/.pyenv/versions/3.7.3/lib/python3.7/site-
packages/ansiblelint/rules, unless -R is also used.
-R Use default rules in
/Users/koh/.pyenv/versions/3.7.3/lib/python3.7/site-
packages/ansiblelint/rules in addition to any extra
rules directories specified with -r. There is no need
to specify this if no -r flags are used
-t TAGS only check rules whose id/tags match these values
-T list all the tags
-v Increase verbosity level
-x SKIP_LIST only check rules whose id/tags do not match these
values
--nocolor disable colored output
--force-color Try force colored output (relying on ansible's code)
--exclude=EXCLUDE_PATHS
path to directories or files to skip. This option is
repeatable.
-c C Specify configuration file to use. Defaults to
".ansible-lint"
[koh@kohs-MBP] ~/work/linttest
%
Basically, you can configure everything with command line options but it is better to use a configuration file to share with your team, or to implement into CI.
Next is how to configure with a file.
Configuration file
It should be placed at ./.ansible-lint
by default, or a file which specified with the option -c
.
This is an example from the official doc.
exclude_paths:
- ./my/excluded/directory/
- ./my/other/excluded/directory/
- ./last/excluded/directory/
parseable: true
quiet: true
rulesdir:
- ./rule/directory/
skip_list:
- skip_this_tag
- and_this_one_too
- skip_this_id
- '401'
tags:
- run_this_tag
use_default_rules: true
verbosity: 1
https://docs.ansible.com/ansible-lint/configuring/configuring.html#configuration-file
exclude_paths (--exclude)
Specify paths or files to exclude from lint.
parseable (-p)
Change the format of the output.
Each error will be converted to one line.
# parseable: false
[koh@kohs-MBP] ~/work/linttest
% ansible-lint site.yml
[201] Trailing whitespace
/Users/koh/work/linttest/roles/201/tasks/main.yml:4
msg: hello
[202] Octal file permissions must contain leading zero or be a string
/Users/koh/work/linttest/roles/202/tasks/main.yml:2
Task/Handler: error 202
[203] Most files should not contain tabs
/Users/koh/work/linttest/roles/203/tasks/main.yml:4
msg: " tab"
[koh@kohs-MBP] ~/work/linttest
%
# parseable: true
[koh@kohs-MBP] ~/work/linttest
% ansible-lint site.yml
/Users/koh/work/linttest/roles/201/tasks/main.yml:4: [E201] Trailing whitespace
/Users/koh/work/linttest/roles/202/tasks/main.yml:2: [E202] Octal file permissions must contain leading zero or be a string
/Users/koh/work/linttest/roles/203/tasks/main.yml:4: [E203] Most files should not contain tabs
[koh@kohs-MBP] ~/work/linttest
%
quiet (-q)
Reduce output.
Not completely 0 but a bit reduced.
# quiet: true
[koh@kohs-MBP] ~/work/linttest
% ansible-lint site.yml
[201] /Users/koh/work/linttest/roles/201/tasks/main.yml:4
[202] /Users/koh/work/linttest/roles/202/tasks/main.yml:2
[203] /Users/koh/work/linttest/roles/203/tasks/main.yml:4
[koh@kohs-MBP] ~/work/linttest
%
rulesdir (-r)
Specify files or directories in which you put original rule files.
skip_list (-x)
Specify tags or error IDs that should be skipped.
You can check about tags with -T
option.
[koh@kohs-MBP] ~/work/linttest
% ansible-lint -T
ANSIBLE0002 ['[201]']
ANSIBLE0004 ['[401]']
ANSIBLE0005 ['[402]']
ANSIBLE0006 ['[303]']
ANSIBLE0007 ['[302]']
ANSIBLE0008 ['[103]']
ANSIBLE0009 ['[202]']
ANSIBLE0010 ['[403]']
ANSIBLE0011 ['[502]']
ANSIBLE0012 ['[301]']
ANSIBLE0013 ['[305]']
ANSIBLE0014 ['[304]']
ANSIBLE0015 ['[104]']
ANSIBLE0016 ['[503]']
ANSIBLE0017 ['[501]']
ANSIBLE0018 ['[101]']
ANSIBLE0019 ['[102]']
behaviour ['[503]']
bug ['[304]']
command-shell ['[305]', '[302]', '[304]', '[306]', '[301]', '[303]']
deprecated ['[105]', '[104]', '[103]', '[101]', '[102]']
formatting ['[104]', '[203]', '[201]', '[204]', '[206]', '[205]', '[202]']
idempotency ['[301]']
idiom ['[601]', '[602]']
metadata ['[701]', '[704]', '[703]', '[702]']
module ['[404]', '[401]', '[403]', '[402]']
oddity ['[501]']
readability ['[502]']
repeatability ['[401]', '[403]', '[402]']
resources ['[302]', '[303]']
safety ['[305]']
task ['[502]', '[503]', '[504]', '[501]']
[koh@kohs-MBP] ~/work/linttest
%
tags (-t)
Opposite of skip_list, specify tags that you want to check.
use_default_rules (-R)
If True, default rules are applied.
If you want to check only your original rules, set it to False.
verbosity (-v)
Specify the verbosity of the output.
It only takes 2 kinds of values which are 0 or greater than 0.
for file in files:
if self.verbosity > 0:
print("Examining %s of type %s" % (file['path'], file['type']))
matches.extend(self.rules.run(file, tags=set(self.tags),
skip_list=self.skip_list))
Configure inside Playbook
By adding a comment, you can skip checks by lines.
Below is an example of the Playbook.
[koh@kohs-MBP] ~/work/linttest
% cat site.yml
---
- hosts: all
tasks:
- name: install latest httpd
yum:
name: httpd
state: latest
- name: install mysql
yum:
name: mysql
state: installed
[koh@kohs-MBP] ~/work/linttest
%
This playbook throws 403 error.
[koh@kohs-MBP] ~/work/linttest
% ansible-lint site.yml
[403] Package installs should not use latest
site.yml:4
Task/Handler: install latest httpd
[koh@kohs-MBP] ~/work/linttest
%
If you really want to keep your httpd updated but not other packages, you can do like below. (you still should not do that though.)
[koh@kohs-MBP] ~/work/linttest
% cat site.yml
---
- hosts: all
tasks:
- name: install latest httpd
yum:
name: httpd
state: latest # noqa 403
- name: install mysql
yum:
name: mysql
state: installed
[koh@kohs-MBP] ~/work/linttest
%
By adding # noqa ID
, the line will be skipped from checks.
[koh@kohs-MBP] ~/work/linttest
% ansible-lint site.yml
[koh@kohs-MBP] ~/work/linttest
%
Original rules
You can create your own rules.
There are some explanations on README and also I recommend you to have a look at scripts of the default rules.
https://github.com/ansible/ansible-lint#creating-custom-rules
https://github.com/ansible/ansible-lint/tree/master/lib/ansiblelint/rules
Here is my example of how to create my own rule.
[koh@kohs-MBP] ~/work/linttest
% cat origrules/True4BooleanRule.py
from ansiblelint import AnsibleLintRule
class True4BooleanRule(AnsibleLintRule):
id = '99'
shortdesc = 'Use "True" for boolean'
description = 'We should "True" for boolean not "yes" or "true".'
tags = ['formatting']
def match(self, file, line):
return ': yes' in line or ': true' in line
[koh@kohs-MBP] ~/work/linttest
%
Playbook can take yes
, true
to set True
for boolean.
With this rule, it throws errors if yes
or true
are used.
*This is a really cheap script only for this explanation please use it with your own risk.
In .ansible-lint
[koh@kohs-MBP] ~/work/linttest
% cat .ansible-lint
rulesdir:
- ./origrules/
[koh@kohs-MBP] ~/work/linttest
%
With this site.yml, it throws 2 errors as intended.
[koh@kohs-MBP] ~/work/linttest
% cat site.yml
--------
- hosts: all
tasks:
- name: this should be error
service:
name: httpd
state: started
enabled: yes
- name: this should be error too
service:
name: mysqld
state: started
enabled: true
- name: this is ok
service:
name: haproxy
state: started
enabled: True
[koh@kohs-MBP] ~/work/linttest
% ansible-lint site.yml
[99] Use "True" for boolean
site.yml:8
enabled: yes
[99] Use "True" for boolean
site.yml:14
enabled: true
[koh@kohs-MBP] ~/work/linttest
%
Conclusion
Creating own rules is much easier than I expected.
So it is good to try one.
Top comments (0)