DEV Community

koh-sh
koh-sh

Posted on

Configuration of ansible-lint

ansible-lint is a tool to check Ansible Playbook.

GitHub logo ansible-community / ansible-lint

Best practices checker for Ansible

PyPI version Ansible-lint rules explanation Ansible Code of Conduct Discussions GitHub Actions CI/CD Language grade: Python pre-commit

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode
# 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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

https://github.com/ansible/ansible-lint/blob/5170c04201e71400421b27255280902c211f8548/lib/ansiblelint/__init__.py#L281

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

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
%
Enter fullscreen mode Exit fullscreen mode

Conclusion

Creating own rules is much easier than I expected.
So it is good to try one.

Top comments (0)