DEV Community

koh-sh
koh-sh

Posted on

Configuration of ansible-lint

ansible-lint is a tool to check Ansible Playbook.

GitHub logo ansible / ansible-lint

ansible-lint checks playbooks for practices and behavior that could potentially be improved and can fix some of the most common ones for you

PyPI version Ansible-lint rules explanation Discussions pre-commit

Ansible-lint

ansible-lint checks playbooks for practices and behavior 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

Using ansible-lint as a GitHub Action

This action allows you to run ansible-lint on your codebase without having to install it yourself.

# .github/workflows/ansible-lint.yml
name: ansible-lint
on:
  pull_request:
    branches: ["main", "stable", "release/v*"]
jobs:
  build:
    name: Ansible Lint # Naming the build is important to use it as a status check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run ansible-lint
        uses: ansible/ansible-lint@main
        # optional (see below):
        with:
          args: ""
          setup_python: "true"
          working_directory: ""
          requirements_file: ""
Enter fullscreen mode Exit fullscreen mode

All the arguments are optional and most users should not need them:

  • args: Arguments to be passed to ansible-lint…

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)