Default Rules¶
Below you can see the list of default rules Ansible Lint use to evaluate playbooks and roles:
command-instead-of-module¶
Using command rather than module.
Executing a command when there is an Ansible module is generally a bad idea
command-instead-of-shell¶
Use shell only when shell functionality is required.
Shell should only be used when piping, redirecting or chaining commands (and Ansible would be preferred for some of those!)
deprecated-bare-vars¶
This rule identifies possible confusing expressions where it is not clear if a variable or string is to be used and asks for clarification.
You should either use the full variable syntax (‘{{{{ {0} }}}}’) or, whenever possible, convert it to a list of strings.
Problematic code¶
---
- ansible.builtin.debug:
msg: "{{ item }}"
with_items: foo # <-- deprecated-bare-vars
Correct code¶
---
# if foo is not really a variable:
- ansible.builtin.debug:
msg: "{{ item }}"
with_items:
- foo
# if foo is a variable:
- ansible.builtin.debug:
msg: "{{ item }}"
with_items: "{{ foo }}"
deprecated-command-syntax¶
Using command rather than an argument to e.g. file.
Executing a command when there are arguments to modules is generally a bad idea
deprecated-local-action¶
Do not use ‘local_action’, use ‘delegate_to: localhost’.
Do not use local_action
, use delegate_to: localhost
deprecated-module¶
Deprecated module.
These are deprecated modules, some modules are kept temporarily for backwards compatibility but usage is discouraged. more
fqcn-builtins¶
Use FQCN for builtin actions.
Check whether the long version starting with ansible.builtin
is used in the playbook
git-latest¶
Git checkouts must contain explicit version.
All version control checkouts must point to an explicit commit or tag, not just latest
hg-latest¶
Mercurial checkouts must contain explicit revision.
All version control checkouts must point to an explicit commit or tag, not just latest
ignore-errors¶
Use failed_when and specify error conditions instead of using ignore_errors.
Instead of ignoring all errors, ignore the errors only when using {{ ansible_check_mode }}
, register the errors using register
, or use failed_when:
and specify acceptable error conditions to reduce the risk of ignoring important failures.
inline-env-var¶
Command module does not accept setting environment variables inline.
Use environment:
to set environment variables or use shell
module which accepts both
internal-error¶
Unexpected internal error.
This error can be caused by internal bugs but also by custom rules. Instead of just stopping linter we generate the errors and continue processing. This allows users to add this rule to their warn list until the root cause is fixed.
key-order¶
Ensure specific order of keys in mappings.
literal-compare¶
Don’t compare to literal True/False.
Use when: var
rather than when: var == True
(or conversely when: not var
)
load-failure¶
Linter failed to process a YAML file, probably because it is either:
contains unsupported encoding (only UTF-8 is supported)
not an Ansible file
it contains some unsupported custom YAML objects (
!!
prefix)it was not able to decrypt an inline
!vault
block.
This violation is not skippable, so it cannot be added to the warn_list
or the skip_list
. If a vault decryption issue cannot be avoided, the
offending file can be added to exclude_paths
configuration.
meta-incorrect¶
meta/main.yml default values should be changed.
meta/main.yml default values should be changed for: author, company, description, license
meta-no-info¶
meta/main.yml should contain relevant info.
meta/main.yml should contain: author, description, license, min_ansible_version, platforms
meta-no-tags¶
Tags must contain lowercase letters and digits only.
Tags must contain lowercase letters and digits only, and galaxy_tags
is expected to be a list
meta-video-links¶
meta/main.yml video_links should be formatted correctly.
Items in video_links
in meta/main.yml should be dictionaries, and contain only keys url
and title
, and have a shared link from a supported provider
no-changed-when¶
Commands should not change things if nothing needs doing.
Tasks should tell Ansible when to return changed
, unless the task only reads
information. To do this, set changed_when
, use the creates
or
removes
argument, or use when
to run the task only if another check has
a particular result.
For example, this task registers the shell
output and uses the return code
to define when the task has changed.
- name: handle shell output with return code
ansible.builtin.shell: cat {{ my_file|quote }}
register: my_output
changed_when: my_output.rc != 0
The following example will trigger the rule since the task does not
handle the output of the command
.
- name: does not handle any output or return codes
ansible.builtin.command: cat {{ my_file|quote }}
no-handler¶
Tasks that run when changed should likely be handlers.
If a task has a when: result.changed
setting, it is effectively acting as a handler. You could use notify and move that task to handlers. more
no-jinja-nesting¶
Nested jinja pattern.
There should not be any nested jinja pattern. Example (bad): {{ list_one + {{ list_two | max }} }}
, Example (good): {{ list_one + max(list_two) }}
, Example (allowed): --format='{{'{{'}}.Size{{'}}'}}'
no-jinja-when¶
No Jinja2 in when.
when
is a raw Jinja2 expression, remove redundant {{ }} from variable(s).
no-loop-var-prefix¶
Role loop_var should use configured prefix.
Looping inside roles has the risk of clashing with loops from user-playbooks. more
no-relative-paths¶
Doesn’t need a relative path in role.
copy
and template
do not need to use relative path for src
package-latest¶
Package installs should not use latest.
Package installs should use state=present
with or without a version
partial-become¶
become_user requires become to work as expected.
become_user
without become
will not actually change user
playbook-extension¶
Use “.yml” or “.yaml” playbook extension.
Playbooks should have the “.yml” or “.yaml” extension
risky-file-permissions¶
File permissions unset or incorrect.
Missing or unsupported mode parameter can cause unexpected file permissions based on version of Ansible being used. Be explicit, like mode: 0644
to avoid hitting this rule. Special preserve
value is accepted only by copy, template modules. more
risky-octal¶
Octal file permissions must contain leading zero or be a string.
Numeric file permissions without leading zero can behave in unexpected ways. more
risky-shell-pipe¶
Shells that use pipes should set the pipefail option.
Without the pipefail option set, a shell command that implements a pipeline can fail and still return 0. If any part of the pipeline other than the terminal command fails, the whole pipeline will still return 0, which may be considered a success by Ansible. Pipefail is available in the bash shell.
role-name¶
Role name {0} does not match ^[a-z][a-z0-9_]+$
pattern.
Role names are now limited to contain only lowercase alphanumeric characters, plus underline and start with an alpha character. more
schema¶
Perform JSON Schema Validation for known lintable kinds.
Returned errors will not include exact line numbers, but they will mention
the schema name being used as a tag, like playbook-schema
,
tasks-schema
.
This rule is not skippable and stops further processing of the file.
Schema bugs should be reported towards schemas project instead of ansible-lint.
If incorrect schema was picked, you might want to either:
move the file to standard location, so its file is detected correctly.
use
kinds:
option in linter config to help it pick correct file type.
syntax-check¶
Ansible syntax check failed.
Running ansible-playbook --syntax-check ...
failed.
This error cannot be disabled due to being a prerequisite for other steps.
You can either exclude these files from linting or better assure they can be
loaded by Ansible. This is often achieved by editing inventory file and/or
ansible.cfg
so ansible can load required variables.
If undefined variables are the failure reason you could use jinja default() filter in order to provide fallback values.
unnamed-task¶
All tasks should be named.
All tasks should have a distinct name for readability and for --start-at-task
to work
var-naming¶
All variables should be named using only lowercase and underscores.
var-spacing¶
Variables and filters in Jinja2 should have spaces before and after, like
{{ var_name | filter }}.
. This improves readability and makes it
less likely to introduce typos.
Problematic code¶
---
foo: "{{some|dict2items}}"
Correct code¶
---
foo: "{{ some | dict2items }}"
yaml¶
Our linter also includes violations reported by yamllint but it uses a slightly different default configuration. We will still load custom yamllint configuration files, but the defaults come from ansible-lint, not from yamllint.
You can fully disable all yamllint violations by adding yaml
to the skip_list
.
Specific tag identifiers that are printed at the end of rule name,
like yaml[trailing-spaces]
or yaml[indentation]
can also be be skipped, allowing
you to have a more fine control.
Problematic code¶
# missing document-start
foo: ...
foo: ... # <-- key-duplicates
bar: ... # <-- wrong comment indentation
Correct code¶
---
foo: ...
bar: ... # comment