使用¶
使用命令¶
安装 Ansible-lint 后,运行 ansible-lint --help
以显示可用命令及其选项。
$ ansible-lint --help
usage: ansible-lint [-h] [-P | -L | -T]
[-f {brief,full,md,json,codeclimate,quiet,pep8,sarif}]
[--sarif-file SARIF_FILE] [-q]
[--profile {min,basic,moderate,safety,shared,production}]
[-p] [--project-dir PROJECT_DIR] [-r RULESDIR] [-R] [-s]
[--fix [WRITE_LIST]] [--show-relpath] [-t TAGS] [-v]
[-x SKIP_LIST] [--generate-ignore] [-w WARN_LIST]
[--enable-list ENABLE_LIST] [--nocolor] [--force-color]
[--exclude EXCLUDE_PATHS [EXCLUDE_PATHS ...]]
[-c CONFIG_FILE] [-i IGNORE_FILE] [--offline] [--version]
[lintables ...]
positional arguments:
lintables One or more files or paths. When missing it will enable auto-detection mode.
options:
-h, --help show this help message and exit
-P, --list-profiles List all profiles.
-L, --list-rules List all the rules.
-T, --list-tags List all the tags and the rules they cover.
-f {brief,full,md,json,codeclimate,quiet,pep8,sarif}, --format {brief,full,md,json,codeclimate,quiet,pep8,sarif}
stdout formatting, json being an alias for codeclimate. (default: None)
--sarif-file SARIF_FILE
SARIF output file
-q quieter, reduce verbosity, can be specified twice.
--profile {min,basic,moderate,safety,shared,production}
Specify which rules profile to be used.
-p, --parseable parseable output, same as '-f pep8'
--project-dir PROJECT_DIR
Location of project/repository, autodetected based on location of configuration file.
-r RULESDIR, --rules-dir RULESDIR
Specify custom rule directories. Add -R to keep using embedded rules from /home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/src/ansiblelint/rules
-R Keep default rules when using -r
-s, --strict Return non-zero exit code on warnings as well as errors
--fix [WRITE_LIST] Allow ansible-lint to perform auto-fixes, including YAML reformatting. You can limit the effective rule transforms (the 'write_list') by passing a keywords 'all' or 'none' or a comma separated list of rule ids or rule tags. YAML reformatting happens whenever '--fix' or '--fix=' is used. '--fix' and '--fix=all' are equivalent: they allow all transforms to run. Presence of --fix in command overrides config file value.
--show-relpath Display path relative to CWD
-t TAGS, --tags TAGS only check rules whose id/tags match these values
-v Increase verbosity level (-vv for more)
-x SKIP_LIST, --skip-list SKIP_LIST
only check rules whose id/tags do not match these values. e.g: --skip-list=name,run-once
--generate-ignore Generate a text file '.ansible-lint-ignore' that ignores all found violations. Each line contains filename and rule id separated by a space.
-w WARN_LIST, --warn-list WARN_LIST
only warn about these rules, unless overridden in config file. Current version default value is: experimental, jinja[spacing], fqcn[deep]
--enable-list ENABLE_LIST
activate optional rules by their tag name
--nocolor disable colored output, same as NO_COLOR=1
--force-color Force colored output, same as FORCE_COLOR=1
--exclude EXCLUDE_PATHS [EXCLUDE_PATHS ...]
path to directories or files to skip. This option is repeatable.
-c CONFIG_FILE, --config-file CONFIG_FILE
Specify configuration file to use. By default it will look for '.ansible-lint', '.ansible-lint.yml', '.ansible-lint.yaml', '.config/ansible-lint.yml', or '.config/ansible-lint.yaml'
-i IGNORE_FILE, --ignore-file IGNORE_FILE
Specify ignore file to use. By default it will look for '.ansible-lint-ignore' or '.config/ansible-lint-ignore.txt'
--offline Disable installation of requirements.yml and schema refreshing
--version
The following environment variables are also recognized but there is no guarantee that they will work in future versions:
ANSIBLE_LINT_CUSTOM_RULESDIR: Used for adding another folder into the lookup path for new rules.
ANSIBLE_LINT_IGNORE_FILE: Define it to override the name of the default ignore file `.ansible-lint-ignore`
ANSIBLE_LINT_WRITE_TMP: Tells linter to dump fixes into different temp files instead of overriding original. Used internally for testing.
ANSIBLE_LINT_SKIP_SCHEMA_UPDATE: Tells ansible-lint to skip schema refresh.
ANSIBLE_LINT_NODEPS: Avoids installing content dependencies and avoids performing checks that would fail when modules are not installed. Far less violations will be reported.
命令输出¶
Ansible-lint 在 stdout
和 stderr
上打印输出。
stdout
显示规则违规。stderr
显示日志和自由格式的消息,例如统计信息。
大多数 ansible-lint
示例使用 pep8 作为输出格式 (-p
),它是机器可解析的。
当检测到 GITHUB_ACTIONS=true
和 GITHUB_WORKFLOW=...
变量时,Ansible-lint 还使用其注释格式打印错误。
缓存¶
为了获得最佳性能,Ansible-lint 会在 {project_dir}/.cache
文件夹中创建已安装或模拟的角色、集合和模块的缓存。{project_dir}
的位置通过命令行参数传递,由配置文件的位置、git 项目顶层目录或用户主目录确定。
为了更快地重新运行,Ansible-lint 不会自动清除缓存。如果需要,您可以手动删除 .cache
文件夹来清除缓存。Ansible-lint 将在下一次调用时创建新的缓存。
您应该将 .cache
文件夹添加到 git 仓库中的 .gitignore
文件中。
逐步采用¶
为了更容易地逐步采用,采用者应该考虑使用忽略文件功能。这允许快速引入 linter 管道以防止添加新的违规行为,而已知的违规行为将被忽略。一些人可以致力于解决这些历史违规行为,而其他人可以继续进行其他维护任务。
已弃用的 --progressive
模式已在 v6.16.0 中删除,因为它增加了代码复杂性和性能开销。它还存在一些在预期情况下无法正常工作并导致误报的极端情况。
检查 playbook 和角色¶
Ansible-lint 建议遵循集合结构布局,无论您是否计划构建集合。
遵循该布局可确保与所有生态系统工具的最佳集成,因为它可以帮助这些工具更好地区分随机 YAML 文件和 Ansible 管理的文件。当您不带参数调用 ansible-lint
时,它会使用内部启发式方法来确定文件类型。
将您想要检查的**角色**和**playbook**作为参数传递给 ansible-lint
命令。例如,要检查 examples/playbooks/play.yml
和 examples/roles/bobbins
,请使用以下命令:
$ ansible-lint examples/playbooks/play.yml examples/roles/bobbins
WARNING Skipped installing collection dependencies due to running in offline mode.
WARNING Listing 6 violation(s) that are fatal
Read documentation for instructions on how to ignore specific rule violations.
# Rule Violation Summary
1 command-instead-of-module profile:basic tags:command-shell,idiom
1 name profile:basic tags:idiom
1 latest profile:basic tags:idempotency
1 no-changed-when profile:basic tags:command-shell,idempotency
1 fqcn profile:basic tags:formatting
1 args profile:basic tags:syntax,experimental
Failed: 5 failure(s), 1 warning(s) on 4 files. Last profile that met the validation criteria was 'min'.
name[play]: All plays should be named.
examples/playbooks/play.yml:2
command-instead-of-module: service used in place of service module
examples/playbooks/play.yml:5 Task/Handler: A bad play
no-changed-when: Commands should not change things if nothing needs doing.
examples/playbooks/play.yml:5 Task/Handler: A bad play
args[module]: missing required arguments: repo (warning)
examples/roles/bobbins/tasks/main.yml:2 Task/Handler: Test tasks
fqcn[action-core]: Use FQCN for builtin module actions (git).
examples/roles/bobbins/tasks/main.yml:2 Use `ansible.builtin.git` or `ansible.legacy.git` instead.
latest[git]: Result of the command may vary on subsequent runs.
examples/roles/bobbins/tasks/main.yml:2 Task/Handler: Test tasks
运行示例 playbook¶
Ansible-lint 包含一个 ansible-lint/examples
文件夹,其中包含具有不同规则违规和不良特征的示例 playbook。您可以对示例 playbook 运行 ansible-lint
以观察 Ansible-lint 的运行情况,如下所示:
$ ansible-lint --offline -p examples/playbooks/example.yml
WARNING Skipped installing collection dependencies due to running in offline mode.
WARNING Listing 22 violation(s) that are fatal
Read documentation for instructions on how to ignore specific rule violations.
# Rule Violation Summary
2 command-instead-of-module profile:basic tags:command-shell,idiom
2 jinja profile:basic tags:formatting
4 no-free-form profile:basic tags:syntax,risk
1 schema profile:basic tags:core
2 name profile:basic tags:idiom
3 latest profile:basic tags:idempotency
2 package-latest profile:basic tags:idempotency
3 no-changed-when profile:basic tags:command-shell,idempotency
3 args profile:basic tags:syntax,experimental
Failed: 19 failure(s), 3 warning(s) on 1 files. Last profile that met the validation criteria was 'min'.
examples/playbooks/example.yml:1: schema[playbook][/]: $[0].tasks[13] None is not of type 'object'[/]
examples/playbooks/example.yml:9: jinja[spacing][/]: Jinja2 spacing could be improved: echo {{this_variable}} is not set in this playbook -> echo {{ this_variable }} is not set in this playbook
examples/playbooks/example.yml:9: no-changed-when: Commands should not change things if nothing needs doing.
examples/playbooks/example.yml:12: no-changed-when: Commands should not change things if nothing needs doing.
examples/playbooks/example.yml:15: args[module][/]: missing required arguments: repo (warning)
examples/playbooks/example.yml:15: latest[git][/]: Result of the command may vary on subsequent runs.
examples/playbooks/example.yml:18: args[module][/]: missing required arguments: repo (warning)
examples/playbooks/example.yml:18: latest[git][/]: Result of the command may vary on subsequent runs.
examples/playbooks/example.yml:21: args[module][/]: Unsupported parameters for (basic.py) module: bobbins. Supported parameters include: accept_hostkey, accept_newhostkey, archive, archive_prefix, bare, clone, depth, dest, executable, force, gpg_allowlist, key_file, recursive, reference, refspec, remote, repo, separate_git_dir, single_branch, ssh_opts, track_submodules, umask, update, verify_commit, version (gpg_whitelist, name). (warning)
examples/playbooks/example.yml:21: no-free-form: Avoid using free-form when calling module actions. (ansible.builtin.git)
examples/playbooks/example.yml:24: command-instead-of-module: git used in place of git module
examples/playbooks/example.yml:24: no-changed-when: Commands should not change things if nothing needs doing.
examples/playbooks/example.yml:27: command-instead-of-module: git used in place of git module
examples/playbooks/example.yml:30: latest[git][/]: Result of the command may vary on subsequent runs.
examples/playbooks/example.yml:33: jinja[spacing][/]: Jinja2 spacing could be improved: {{item}} -> {{ item }}
examples/playbooks/example.yml:39: no-free-form: Avoid using free-form when calling module actions. (ansible.builtin.dnf)
examples/playbooks/example.yml:39: package-latest: Package installs should not use latest.
examples/playbooks/example.yml:42: name[missing][/]: All tasks should be named.
examples/playbooks/example.yml:42: no-free-form: Avoid using free-form when calling module actions. (ansible.builtin.debug)
examples/playbooks/example.yml:44: no-free-form: Avoid using free-form when calling module actions. (ansible.builtin.apt)
examples/playbooks/example.yml:44: package-latest: Package installs should not use latest.
examples/playbooks/example.yml:47: name[missing][/]: All tasks should be named.
Ansible-lint 还处理包含其他 playbook、任务、处理程序或角色的 playbook,如 examples/playbooks/include.yml
示例所示。
$ ansible-lint --offline -q -p examples/playbooks/include.yml
examples/playbooks/handlers/y.yml:2: fqcn[action-core]
examples/playbooks/include.yml:13:7: syntax-check[specific][/]
examples/playbooks/play.yml:2: name[play][/]
examples/playbooks/play.yml:5: command-instead-of-module
examples/playbooks/play.yml:5: no-changed-when
examples/playbooks/tasks/x.yml:1: schema[tasks][/]
examples/playbooks/tasks/x.yml:3: name[prefix][/]
examples/roles/more_complex/handlers/main.yml:2: command-instead-of-module
examples/roles/more_complex/handlers/main.yml:2: fqcn[action-core]
examples/roles/more_complex/handlers/main.yml:2: no-changed-when
examples/roles/more_complex/tasks/main.yml:2: fqcn[action-core]
examples/roles/more_complex/tasks/main.yml:2: no-changed-when
examples/roles/more_complex/tasks/main.yml:5: fqcn[action-core]
examples/roles/more_complex/tasks/main.yml:5: no-changed-when
examples/roles/more_complex/tasks/main.yml:8: command-instead-of-shell
examples/roles/more_complex/tasks/main.yml:8: deprecated-local-action
examples/roles/more_complex/tasks/main.yml:8: fqcn[action-core]
examples/roles/more_complex/tasks/main.yml:8: no-changed-when
输出格式¶
pep8¶
$ ansible-lint --offline -q -f pep8 examples/playbooks/norole.yml
examples/playbooks/handlers/y.yml:2: fqcn[action-core]
examples/playbooks/norole.yml:5:7: syntax-check[specific][/]
examples/playbooks/tasks/bug-2875.yml:2: fqcn[action-core]
examples/playbooks/tasks/bug-2875.yml:2: name[prefix][/]
examples/playbooks/tasks/directory with spaces/main.yml:3: name[missing][/]
examples/playbooks/tasks/empty_blocks.yml:1: schema[tasks][/]
examples/playbooks/tasks/empty_blocks.yml:2: name[prefix][/]
examples/playbooks/tasks/empty_blocks.yml:4: name[prefix][/]
examples/playbooks/tasks/empty_blocks.yml:9: name[missing][/]
examples/playbooks/tasks/empty_blocks.yml:10: name[prefix][/]
examples/playbooks/tasks/empty_blocks.yml:15: name[prefix][/]
examples/playbooks/tasks/include-in-block-inner.yml:4: name[prefix][/]
examples/playbooks/tasks/included-with-lint.yml:3: name[missing][/]
examples/playbooks/tasks/local_action.transformed.yml:2: name[prefix][/]
examples/playbooks/tasks/local_action.transformed.yml:2: no-changed-when
examples/playbooks/tasks/local_action.yml:2: deprecated-local-action
examples/playbooks/tasks/local_action.yml:2: fqcn[action-core]
examples/playbooks/tasks/local_action.yml:2: name[prefix][/]
examples/playbooks/tasks/local_action.yml:2: no-changed-when
examples/playbooks/tasks/malformed.yml:1: load-failure
examples/playbooks/tasks/nestedincludes.yml:2: fqcn[action-core]
examples/playbooks/tasks/nestedincludes.yml:2: name[prefix][/]
examples/playbooks/tasks/partial_become.yml/main.yml:2: name[prefix][/]
examples/playbooks/tasks/partial_prefix/foo.yml:2: name[prefix][/]
examples/playbooks/tasks/partial_prefix/foo.yml:5: name[prefix][/]
examples/playbooks/tasks/partial_prefix/main.yml:5: name[prefix][/]
examples/playbooks/tasks/partial_prefix/main.yml:8: name[prefix][/]
examples/playbooks/tasks/rule-name-prefix-fail.yml:2: name[casing][/]
examples/playbooks/tasks/rule-name-prefix-fail.yml:5: name[prefix][/]
examples/playbooks/tasks/rule-name-prefix-fail.yml:8: name[prefix][/]
examples/playbooks/tasks/varset.yml:2: fqcn[action-core]
examples/playbooks/tasks/varset.yml:2: name[missing][/]
examples/playbooks/tasks/varset.yml:2: no-free-form
examples/playbooks/tasks/varset.yml:4: fqcn[action-core]
examples/playbooks/tasks/varset.yml:4: latest[git][/]
examples/playbooks/tasks/varset.yml:4: name[missing][/]
examples/playbooks/tasks/varset.yml:4: no-free-form
examples/playbooks/tasks/varunset.yml:2: fqcn[action-core]
examples/playbooks/tasks/varunset.yml:2: name[missing][/]
examples/playbooks/tasks/varunset.yml:2: no-free-form
examples/playbooks/tasks/x.yml:1: schema[tasks][/]
examples/playbooks/tasks/x.yml:3: name[prefix][/]
examples/playbooks/vars/empty.transformed.yml:1: yaml[trailing-spaces]
examples/playbooks/vars/empty.yml:1: yaml[trailing-spaces]
examples/playbooks/vars/invalid_vars_schema.yml:1: schema[vars][/]
examples/playbooks/vars/jinja-spacing.yml:14: jinja[spacing][/]
examples/playbooks/vars/jinja-spacing.yml:15: jinja[spacing][/]
examples/playbooks/vars/jinja-spacing.yml:16: jinja[spacing][/]
examples/playbooks/vars/jinja-spacing.yml:17: jinja[spacing][/]
examples/playbooks/vars/jinja-spacing.yml:18: jinja[spacing][/]
examples/playbooks/vars/jinja-spacing.yml:19: jinja[spacing][/]
examples/playbooks/vars/jinja-spacing.yml:32: jinja[spacing][/]
examples/playbooks/vars/rule_var_naming_fail.yml:1: schema[vars][/]
examples/playbooks/vars/rule_var_naming_fail.yml:2: var-naming[pattern][/]
examples/playbooks/vars/rule_var_naming_fail.yml:6: var-naming[pattern][/]
examples/playbooks/vars/rule_var_naming_fail.yml:10: var-naming[no-keyword]
examples/playbooks/vars/rule_var_naming_fail.yml:11: var-naming[non-ascii]
examples/playbooks/vars/rule_var_naming_fail.yml:12: var-naming[no-reserved]
examples/playbooks/vars/rule_var_naming_fail.yml:13: var-naming[read-only]
examples/playbooks/vars/rule_var_naming_fails_files/bar.yml:2: var-naming[pattern][/]
examples/playbooks/vars/rule_var_naming_fails_files/bar.yml:3: var-naming[pattern][/]
examples/playbooks/vars/rule_var_naming_fails_files/foo.yml:2: var-naming[pattern][/]
examples/playbooks/vars/rule_var_naming_fails_files/foo.yml:3: var-naming[pattern][/]
examples/playbooks/vars/strings.transformed.yml:8: yaml[line-length]
examples/playbooks/vars/strings.transformed.yml:14: yaml[line-length]
examples/playbooks/vars/transform_nested_data.yml:3: yaml[hyphens][/]
examples/playbooks/vars/transform_nested_data.yml:6: yaml[hyphens][/]
examples/playbooks/vars/transform_nested_data.yml:7: yaml[hyphens][/]
SARIF JSON¶
使用 --format sarif
或 --format json
,linter 将在 stdout 上输出SARIF格式的报告。
我们还有一个 --sarif-file FILE
选项,可以使 linter 将输出转储到文件,同时不改变其正常的 stdout 输出。这可以在 CI/CD 管道中使用。
{"$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json", "version": "2.1.0", "runs": [{"tool": {"driver": {"name": "ansible-lint", "version": "24.12.3.dev5", "informationUri": "https://github.com/ansible/ansible-lint", "rules": [{"id": "fqcn[action-core]", "name": "fqcn[action-core]", "shortDescription": {"text": "Use FQCN for builtin module actions (service)."}, "defaultConfiguration": {"level": "warning"}, "help": {"text": "Check whether actions are using using full qualified collection names."}, "helpUri": "https://docs.ansible.com/projects/lint/rules/fqcn/", "properties": {"tags": ["formatting"]}}, {"id": "syntax-check[specific]", "name": "syntax-check[specific]", "shortDescription": {"text": "the role 'node' was not found in /home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/examples/playbooks/roles:/home/docs/.cache/ansible-compat/5e1e2b/roles:/home/docs/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:/home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/examples/playbooks"}, "defaultConfiguration": {"level": "error"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/syntax-check/", "properties": {"tags": ["core", "unskippable"]}}, {"id": "name[prefix]", "name": "name[prefix]", "shortDescription": {"text": "Task name should start with 'bug-2875 | '."}, "defaultConfiguration": {"level": "warning"}, "help": {"text": "All tasks and plays should have a distinct name for readability and for ``--start-at-task`` to work"}, "helpUri": "https://docs.ansible.com/projects/lint/rules/name/", "properties": {"tags": ["idiom"]}}, {"id": "name[missing]", "name": "name[missing]", "shortDescription": {"text": "All tasks should be named."}, "defaultConfiguration": {"level": "warning"}, "help": {"text": "All tasks and plays should have a distinct name for readability and for ``--start-at-task`` to work"}, "helpUri": "https://docs.ansible.com/projects/lint/rules/name/", "properties": {"tags": ["idiom"]}}, {"id": "schema[tasks]", "name": "schema[tasks]", "shortDescription": {"text": "$[0].always {} is not of type 'array'"}, "defaultConfiguration": {"level": "error"}, "help": {"text": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}, "helpUri": "https://docs.ansible.com/projects/lint/rules/schema/", "properties": {"tags": ["core"]}}, {"id": "no-changed-when", "name": "no-changed-when", "shortDescription": {"text": "Commands should not change things if nothing needs doing."}, "defaultConfiguration": {"level": "error"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/no-changed-when/", "properties": {"tags": ["command-shell", "idempotency"]}}, {"id": "deprecated-local-action", "name": "deprecated-local-action", "shortDescription": {"text": "Do not use 'local_action', use 'delegate_to: localhost'."}, "defaultConfiguration": {"level": "warning"}, "help": {"text": "Do not use ``local_action``, use ``delegate_to: localhost``"}, "helpUri": "https://docs.ansible.com/projects/lint/rules/deprecated-local-action/", "properties": {"tags": ["deprecations"]}}, {"id": "load-failure", "name": "load-failure", "shortDescription": {"text": "Failed to load or parse file."}, "defaultConfiguration": {"level": "error"}, "help": {"text": "Linter failed to process a file, possible invalid file."}, "helpUri": "https://docs.ansible.com/projects/lint/rules/load-failure/", "properties": {"tags": ["core", "unskippable"]}}, {"id": "name[casing]", "name": "name[casing]", "shortDescription": {"text": "All names should start with an uppercase letter."}, "defaultConfiguration": {"level": "warning"}, "help": {"text": "All tasks and plays should have a distinct name for readability and for ``--start-at-task`` to work"}, "helpUri": "https://docs.ansible.com/projects/lint/rules/name/", "properties": {"tags": ["idiom"]}}, {"id": "no-free-form", "name": "no-free-form", "shortDescription": {"text": "Avoid using free-form when calling module actions. (debug)"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": "Avoid free-form inside files as it can produce subtle bugs."}, "helpUri": "https://docs.ansible.com/projects/lint/rules/no-free-form/", "properties": {"tags": ["syntax", "risk"]}}, {"id": "latest[git]", "name": "latest[git]", "shortDescription": {"text": "Result of the command may vary on subsequent runs."}, "defaultConfiguration": {"level": "warning"}, "help": {"text": "All version control checkouts must point to an explicit commit or tag, not just ``latest``"}, "helpUri": "https://docs.ansible.com/projects/lint/rules/latest/", "properties": {"tags": ["idempotency"]}}, {"id": "yaml[trailing-spaces]", "name": "yaml[trailing-spaces]", "shortDescription": {"text": "Trailing spaces"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/yaml/", "properties": {"tags": ["formatting", "yaml"]}}, {"id": "schema[vars]", "name": "schema[vars]", "shortDescription": {"text": "$ '123' does not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'. See https://docs.ansible.org.cn/ansible/latest/playbook_guide/playbooks_variables.html"}, "defaultConfiguration": {"level": "error"}, "help": {"text": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}, "helpUri": "https://docs.ansible.com/projects/lint/rules/schema/", "properties": {"tags": ["core"]}}, {"id": "jinja[spacing]", "name": "jinja[spacing]", "shortDescription": {"text": "Jinja2 spacing could be improved: {{bad_format}} -> {{ bad_format }}"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/jinja/", "properties": {"tags": ["formatting"]}}, {"id": "var-naming[pattern]", "name": "var-naming[pattern]", "shortDescription": {"text": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (CamelCaseIsBad) (vars: CamelCaseIsBad)"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/var-naming/", "properties": {"tags": ["idiom"]}}, {"id": "var-naming[no-keyword]", "name": "var-naming[no-keyword]", "shortDescription": {"text": "Variables names must not be Python keywords. (assert) (vars: assert)"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/var-naming/", "properties": {"tags": ["idiom"]}}, {"id": "var-naming[non-ascii]", "name": "var-naming[non-ascii]", "shortDescription": {"text": "Variables names must be ASCII. (\u00e9) (vars: \u00e9)"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/var-naming/", "properties": {"tags": ["idiom"]}}, {"id": "var-naming[no-reserved]", "name": "var-naming[no-reserved]", "shortDescription": {"text": "Variables names must not be Ansible reserved names. (hosts) (vars: hosts)"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/var-naming/", "properties": {"tags": ["idiom"]}}, {"id": "var-naming[read-only]", "name": "var-naming[read-only]", "shortDescription": {"text": "This special variable is read-only. (role_name) (vars: role_name)"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/var-naming/", "properties": {"tags": ["idiom"]}}, {"id": "yaml[line-length]", "name": "yaml[line-length]", "shortDescription": {"text": "Line too long (166 > 160 characters)"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/yaml/", "properties": {"tags": ["formatting", "yaml"]}}, {"id": "yaml[hyphens]", "name": "yaml[hyphens]", "shortDescription": {"text": "Too many spaces after hyphen"}, "defaultConfiguration": {"level": "warning"}, "help": {"text": ""}, "helpUri": "https://docs.ansible.com/projects/lint/rules/yaml/", "properties": {"tags": ["formatting", "yaml"]}}]}}, "columnKind": "utf16CodeUnits", "results": [{"ruleId": "fqcn[action-core]", "level": "error", "message": {"text": "Use `ansible.builtin.service` or `ansible.legacy.service` instead."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/handlers/y.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "syntax-check[specific]", "level": "error", "message": {"text": "the role 'node' was not found in /home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/examples/playbooks/roles:/home/docs/.cache/ansible-compat/5e1e2b/roles:/home/docs/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:/home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/examples/playbooks"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/norole.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 5, "startColumn": 7}}}]}, {"ruleId": "fqcn[action-core]", "level": "error", "message": {"text": "Use `ansible.builtin.include_tasks` or `ansible.legacy.include_tasks` instead."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/bug-2875.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: Reproduce bug #2875"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/bug-2875.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[missing]", "level": "error", "message": {"text": "Task/Handler: assert fail_msg=tasks in directory with spaces included"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/directory with spaces/main.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 3}}}]}, {"ruleId": "schema[tasks]", "level": "error", "message": {"text": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/empty_blocks.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 1}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: A named block task"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/empty_blocks.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: an assertion"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/empty_blocks.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 4}}}]}, {"ruleId": "name[missing]", "level": "error", "message": {"text": "Task/Handler: block/always/rescue "}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/empty_blocks.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 9}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: Another assertion"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/empty_blocks.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 10}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: Yet another assertion"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/empty_blocks.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 15}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: simple_task | Include tasks from inside a block"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/include-in-block-inner.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 4}}}]}, {"ruleId": "name[missing]", "level": "error", "message": {"text": "Task/Handler: assert fail_msg=foo"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/included-with-lint.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 3}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: Sample"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/local_action.transformed.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "no-changed-when", "level": "error", "message": {"text": "Task/Handler: Sample"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/local_action.transformed.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "deprecated-local-action", "level": "error", "message": {"text": "Task/Handler: Sample"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/local_action.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "fqcn[action-core]", "level": "error", "message": {"text": "Use `ansible.builtin.command` or `ansible.legacy.command` instead."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/local_action.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: Sample"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/local_action.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "no-changed-when", "level": "error", "message": {"text": "Task/Handler: Sample"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/local_action.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "load-failure", "level": "error", "message": {"text": "Failed to load or parse file."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/malformed.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 1}}}]}, {"ruleId": "fqcn[action-core]", "level": "error", "message": {"text": "Use `ansible.builtin.include_tasks` or `ansible.legacy.include_tasks` instead."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/nestedincludes.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: simple_task | One include"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/nestedincludes.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: Included with partial become"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/partial_become.yml/main.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: foo | This prefix is incomplete"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/partial_prefix/foo.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: partial_prefix | This prefix is incomplete"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/partial_prefix/foo.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 5}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: main | This prefix is incomplete"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/partial_prefix/main.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 5}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: partial_prefix | This prefix is incomplete"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/partial_prefix/main.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 8}}}]}, {"ruleId": "name[casing]", "level": "error", "message": {"text": "Task/Handler: rule-name-prefix-fail | this is not correctly capitalized"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/rule-name-prefix-fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: This is missing the prefix"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/rule-name-prefix-fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 5}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: name | This prefix is incomplete"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/rule-name-prefix-fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 8}}}]}, {"ruleId": "fqcn[action-core]", "level": "error", "message": {"text": "Use `ansible.builtin.debug` or `ansible.legacy.debug` instead."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[missing]", "level": "error", "message": {"text": "Task/Handler: debug msg=var was set"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "no-free-form", "level": "error", "message": {"text": "Task/Handler: debug msg=var was set"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "fqcn[action-core]", "level": "error", "message": {"text": "Use `ansible.builtin.git` or `ansible.legacy.git` instead."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 4}}}]}, {"ruleId": "latest[git]", "level": "error", "message": {"text": "Task/Handler: git repo=hello.git"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 4}}}]}, {"ruleId": "name[missing]", "level": "error", "message": {"text": "Task/Handler: git repo=hello.git"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 4}}}]}, {"ruleId": "no-free-form", "level": "error", "message": {"text": "Task/Handler: git repo=hello.git"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 4}}}]}, {"ruleId": "fqcn[action-core]", "level": "error", "message": {"text": "Use `ansible.builtin.debug` or `ansible.legacy.debug` instead."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varunset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "name[missing]", "level": "error", "message": {"text": "Task/Handler: debug msg=var was not set"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varunset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "no-free-form", "level": "error", "message": {"text": "Task/Handler: debug msg=var was not set"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/varunset.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "schema[tasks]", "level": "error", "message": {"text": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/x.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 1}}}]}, {"ruleId": "name[prefix]", "level": "error", "message": {"text": "Task/Handler: Test include"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/tasks/x.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 3}}}]}, {"ruleId": "yaml[trailing-spaces]", "level": "error", "message": {"text": "Trailing spaces"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/empty.transformed.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 1}}}]}, {"ruleId": "yaml[trailing-spaces]", "level": "error", "message": {"text": "Trailing spaces"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/empty.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 1}}}]}, {"ruleId": "schema[vars]", "level": "error", "message": {"text": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/invalid_vars_schema.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 1}}}]}, {"ruleId": "jinja[spacing]", "level": "error", "message": {"text": "Jinja2 template rewrite recommendation: `{{ bad_format }}`."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/jinja-spacing.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 14}}}]}, {"ruleId": "jinja[spacing]", "level": "error", "message": {"text": "Jinja2 template rewrite recommendation: `Value: {{ bad_format }}`."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/jinja-spacing.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 15}}}]}, {"ruleId": "jinja[spacing]", "level": "error", "message": {"text": "Jinja2 template rewrite recommendation: `{{ bad_format }}`."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/jinja-spacing.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 16}}}]}, {"ruleId": "jinja[spacing]", "level": "error", "message": {"text": "Jinja2 template rewrite recommendation: `{{ bad_format | filter }}`."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/jinja-spacing.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 17}}}]}, {"ruleId": "jinja[spacing]", "level": "error", "message": {"text": "Jinja2 template rewrite recommendation: `Value: {{ bad_format | filter }}`."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/jinja-spacing.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 18}}}]}, {"ruleId": "jinja[spacing]", "level": "error", "message": {"text": "Jinja2 template rewrite recommendation: `{{ bad_format | filter }}`."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/jinja-spacing.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 19}}}]}, {"ruleId": "jinja[spacing]", "level": "error", "message": {"text": "Jinja2 template rewrite recommendation: `{{ {'dummy_2': {'nested_dummy_1': 'value_1', 'nested_dummy_2': value_2}} | combine(dummy_1) }}`."}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/jinja-spacing.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 32}}}]}, {"ruleId": "schema[vars]", "level": "error", "message": {"text": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 1}}}]}, {"ruleId": "var-naming[pattern]", "level": "error", "message": {"text": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (CamelCaseIsBad) (vars: CamelCaseIsBad)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "var-naming[pattern]", "level": "error", "message": {"text": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (ALL_CAPS_ARE_BAD_TOO) (vars: ALL_CAPS_ARE_BAD_TOO)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 6}}}]}, {"ruleId": "var-naming[no-keyword]", "level": "error", "message": {"text": "Variables names must not be Python keywords. (assert) (vars: assert)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 10}}}]}, {"ruleId": "var-naming[non-ascii]", "level": "error", "message": {"text": "Variables names must be ASCII. (\u00e9) (vars: \u00e9)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 11}}}]}, {"ruleId": "var-naming[no-reserved]", "level": "error", "message": {"text": "Variables names must not be Ansible reserved names. (hosts) (vars: hosts)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 12}}}]}, {"ruleId": "var-naming[read-only]", "level": "error", "message": {"text": "This special variable is read-only. (role_name) (vars: role_name)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fail.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 13}}}]}, {"ruleId": "var-naming[pattern]", "level": "error", "message": {"text": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (CamelCaseIsBad) (vars: CamelCaseIsBad)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fails_files/bar.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "var-naming[pattern]", "level": "error", "message": {"text": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (ALL_CAPS_ARE_BAD_TOO) (vars: ALL_CAPS_ARE_BAD_TOO)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fails_files/bar.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 3}}}]}, {"ruleId": "var-naming[pattern]", "level": "error", "message": {"text": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (CamelCaseIsBad) (vars: CamelCaseIsBad)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fails_files/foo.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 2}}}]}, {"ruleId": "var-naming[pattern]", "level": "error", "message": {"text": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (ALL_CAPS_ARE_BAD_TOO) (vars: ALL_CAPS_ARE_BAD_TOO)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/rule_var_naming_fails_files/foo.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 3}}}]}, {"ruleId": "yaml[line-length]", "level": "error", "message": {"text": "Line too long (166 > 160 characters)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/strings.transformed.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 8}}}]}, {"ruleId": "yaml[line-length]", "level": "error", "message": {"text": "Line too long (166 > 160 characters)"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/strings.transformed.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 14}}}]}, {"ruleId": "yaml[hyphens]", "level": "error", "message": {"text": "Too many spaces after hyphen"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/transform_nested_data.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 3}}}]}, {"ruleId": "yaml[hyphens]", "level": "error", "message": {"text": "Too many spaces after hyphen"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/transform_nested_data.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 6}}}]}, {"ruleId": "yaml[hyphens]", "level": "error", "message": {"text": "Too many spaces after hyphen"}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "examples/playbooks/vars/transform_nested_data.yml", "uriBaseId": "SRCROOT"}, "region": {"startLine": 7}}}]}], "originalUriBaseIds": {"SRCROOT": {"uri": "file:///home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/"}}}]}
Code Climate JSON¶
您可以根据Code Climate规范生成 JSON
报告,如 examples/playbooks/norole.yml
示例所示。
[{"type": "issue", "check_name": "fqcn[action-core]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/fqcn/", "severity": "major", "description": "Use FQCN for builtin module actions (service).", "fingerprint": "87b264545a52fafc5a04c9d83b092e2bfb58305a54bb43b2b8cb61b7ad850094", "location": {"path": "examples/playbooks/handlers/y.yml", "lines": {"begin": 2}}, "content": {"body": "Use `ansible.builtin.service` or `ansible.legacy.service` instead."}}, {"type": "issue", "check_name": "syntax-check[specific]", "categories": ["core", "unskippable"], "url": "https://docs.ansible.com/projects/lint/rules/syntax-check/", "severity": "major", "description": "the role 'node' was not found in /home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/examples/playbooks/roles:/home/docs/.cache/ansible-compat/5e1e2b/roles:/home/docs/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:/home/docs/checkouts/readthedocs.org/user_builds/ansible-lint/checkouts/latest/examples/playbooks", "fingerprint": "8baa3f88be792bd42777dd4b689c8ba9d2e49e1f0a789b78dc3a07ac40aaeb20", "location": {"path": "examples/playbooks/norole.yml", "positions": {"begin": {"line": 5, "column": 7}}}}, {"type": "issue", "check_name": "fqcn[action-core]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/fqcn/", "severity": "major", "description": "Use FQCN for builtin module actions (include_tasks).", "fingerprint": "7abb0f071677009e5f3528faa4cf19002ff3f21f19c6a93a4897caf82b44d740", "location": {"path": "examples/playbooks/tasks/bug-2875.yml", "lines": {"begin": 2}}, "content": {"body": "Use `ansible.builtin.include_tasks` or `ansible.legacy.include_tasks` instead."}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'bug-2875 | '.", "fingerprint": "dc44da41e01f2164e6ca404677144a34394a3c4dedab9d632ab4fbf030e69d22", "location": {"path": "examples/playbooks/tasks/bug-2875.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: Reproduce bug #2875"}}, {"type": "issue", "check_name": "name[missing]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "All tasks should be named.", "fingerprint": "fcc3b3cec3938001db450c922039b2741d6958a764db0923f7c1031e4a97b630", "location": {"path": "examples/playbooks/tasks/directory with spaces/main.yml", "lines": {"begin": 3}}, "content": {"body": "Task/Handler: assert fail_msg=tasks in directory with spaces included"}}, {"type": "issue", "check_name": "schema[tasks]", "categories": ["core"], "url": "https://docs.ansible.com/projects/lint/rules/schema/", "severity": "major", "description": "$[0].always {} is not of type 'array'", "fingerprint": "39ab9e8002b7e7db1f0de968c77df1eb317663e520d67d98cda5c07aaa5e4e56", "location": {"path": "examples/playbooks/tasks/empty_blocks.yml", "lines": {"begin": 1}}, "content": {"body": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'empty_blocks | '.", "fingerprint": "37782e9a31383ebd009d3758414e9af1e752e70df23d7404dd9df2c33db42f65", "location": {"path": "examples/playbooks/tasks/empty_blocks.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: A named block task"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'empty_blocks | '.", "fingerprint": "698422e64114eda5b3c7bde83e955d5d6bf610075f965938b71c49dce2abd493", "location": {"path": "examples/playbooks/tasks/empty_blocks.yml", "lines": {"begin": 4}}, "content": {"body": "Task/Handler: an assertion"}}, {"type": "issue", "check_name": "name[missing]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "All tasks should be named.", "fingerprint": "b7d2ca500d3686eddb26ed03e16592ec5ca9c13aac62688a0f06ff529fc639b4", "location": {"path": "examples/playbooks/tasks/empty_blocks.yml", "lines": {"begin": 9}}, "content": {"body": "Task/Handler: block/always/rescue "}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'empty_blocks | '.", "fingerprint": "2c569c04cce1b3c8ee2ed903e2dfb51c75a2ecb5cff538be95ac8ee4689d3725", "location": {"path": "examples/playbooks/tasks/empty_blocks.yml", "lines": {"begin": 10}}, "content": {"body": "Task/Handler: Another assertion"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'empty_blocks | '.", "fingerprint": "2fe9afaa9af6ae2f16824cd64563f3f2a46581205353404fa08c62062d120b4b", "location": {"path": "examples/playbooks/tasks/empty_blocks.yml", "lines": {"begin": 15}}, "content": {"body": "Task/Handler: Yet another assertion"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'include-in-block-inner | '.", "fingerprint": "7a26cfa960e60d6b59be0b3fb6fc95a9ba4604576cdf05e3e945d0e3b6c859e2", "location": {"path": "examples/playbooks/tasks/include-in-block-inner.yml", "lines": {"begin": 4}}, "content": {"body": "Task/Handler: simple_task | Include tasks from inside a block"}}, {"type": "issue", "check_name": "name[missing]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "All tasks should be named.", "fingerprint": "f6a65adf9e3a3ed827955aa6bee49e3411ce1dae7d55a99b87a49e67a626595f", "location": {"path": "examples/playbooks/tasks/included-with-lint.yml", "lines": {"begin": 3}}, "content": {"body": "Task/Handler: assert fail_msg=foo"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'local_action.transformed | '.", "fingerprint": "5cdec9cf40e42c4a4bbf238e539a79375629e4e59e7f9160c51e923564ff7176", "location": {"path": "examples/playbooks/tasks/local_action.transformed.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: Sample"}}, {"type": "issue", "check_name": "no-changed-when", "categories": ["command-shell", "idempotency"], "url": "https://docs.ansible.com/projects/lint/rules/no-changed-when/", "severity": "major", "description": "Commands should not change things if nothing needs doing.", "fingerprint": "87d83f38573a6d07f65faf8b6c9a7148d7cb6a0806429cf0a208d3b5393ddc33", "location": {"path": "examples/playbooks/tasks/local_action.transformed.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: Sample"}}, {"type": "issue", "check_name": "deprecated-local-action", "categories": ["deprecations"], "url": "https://docs.ansible.com/projects/lint/rules/deprecated-local-action/", "severity": "major", "description": "Do not use 'local_action', use 'delegate_to: localhost'.", "fingerprint": "f41c3b2afe82e7bbe573839f96d2216fc03119892bbaaec5d0d4c8b77bb1c7aa", "location": {"path": "examples/playbooks/tasks/local_action.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: Sample"}}, {"type": "issue", "check_name": "fqcn[action-core]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/fqcn/", "severity": "major", "description": "Use FQCN for builtin module actions (command).", "fingerprint": "212c9fb53bc6815069f13f5b54dfb10acd8a66649c6bb6cfaf064130d2eff5d3", "location": {"path": "examples/playbooks/tasks/local_action.yml", "lines": {"begin": 2}}, "content": {"body": "Use `ansible.builtin.command` or `ansible.legacy.command` instead."}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'local_action | '.", "fingerprint": "66e7c7a7732ae0ec71e36294a212bf9b44561e177f02f2222b94f8e3440af279", "location": {"path": "examples/playbooks/tasks/local_action.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: Sample"}}, {"type": "issue", "check_name": "no-changed-when", "categories": ["command-shell", "idempotency"], "url": "https://docs.ansible.com/projects/lint/rules/no-changed-when/", "severity": "major", "description": "Commands should not change things if nothing needs doing.", "fingerprint": "4ca055980be476b39cbb9e3a9ee2fde9aefe1bfdcda29cc4e5c24693b93728b9", "location": {"path": "examples/playbooks/tasks/local_action.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: Sample"}}, {"type": "issue", "check_name": "load-failure", "categories": ["core", "unskippable"], "url": "https://docs.ansible.com/projects/lint/rules/load-failure/", "severity": "major", "description": "Failed to load or parse file.", "fingerprint": "0f53ff9c66914d7f8a5f121275e19ec37a34e134f6fefd27a9858e5542151246", "location": {"path": "examples/playbooks/tasks/malformed.yml", "lines": {"begin": 1}}}, {"type": "issue", "check_name": "fqcn[action-core]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/fqcn/", "severity": "major", "description": "Use FQCN for builtin module actions (include_tasks).", "fingerprint": "0c82a6f80a2dabd79673e964d6931cd83799f0d4743b87a6d96d351c6ac24734", "location": {"path": "examples/playbooks/tasks/nestedincludes.yml", "lines": {"begin": 2}}, "content": {"body": "Use `ansible.builtin.include_tasks` or `ansible.legacy.include_tasks` instead."}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'nestedincludes | '.", "fingerprint": "7ff6f407e8ae1b163c4bf585c3db6bdb24a5868cbc899c9b5f0f1adce7fab7c6", "location": {"path": "examples/playbooks/tasks/nestedincludes.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: simple_task | One include"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'partial_become.yml | main | '.", "fingerprint": "17c1e8cd489fa6154687be4711f523b015b54a4e62a5f338eb9aa3f3e8cf2a5d", "location": {"path": "examples/playbooks/tasks/partial_become.yml/main.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: Included with partial become"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'partial_prefix | foo | '.", "fingerprint": "d40a0b33111210c2b461cf666600094c4948222940ae530fcade9ff2dc2b3dd4", "location": {"path": "examples/playbooks/tasks/partial_prefix/foo.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: foo | This prefix is incomplete"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'partial_prefix | foo | '.", "fingerprint": "e26d3df5de3c2064a0e97170efd4f9107d82d0466a27833467c495e56ab7a876", "location": {"path": "examples/playbooks/tasks/partial_prefix/foo.yml", "lines": {"begin": 5}}, "content": {"body": "Task/Handler: partial_prefix | This prefix is incomplete"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'partial_prefix | main | '.", "fingerprint": "b54d216fbf48928a52a04bbc6ee42ad9bb150ac37d16e6fe4b49661fb26b4508", "location": {"path": "examples/playbooks/tasks/partial_prefix/main.yml", "lines": {"begin": 5}}, "content": {"body": "Task/Handler: main | This prefix is incomplete"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'partial_prefix | main | '.", "fingerprint": "d9f4c3b01fdf8937222cd711415b9e4e9d28735f53caaf13a00987a7fc12afa7", "location": {"path": "examples/playbooks/tasks/partial_prefix/main.yml", "lines": {"begin": 8}}, "content": {"body": "Task/Handler: partial_prefix | This prefix is incomplete"}}, {"type": "issue", "check_name": "name[casing]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "All names should start with an uppercase letter.", "fingerprint": "d67cc3a34e9adfc57d8e6d8632d757959e0f3dda6e2c3c75b1fbbe92da8afebf", "location": {"path": "examples/playbooks/tasks/rule-name-prefix-fail.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: rule-name-prefix-fail | this is not correctly capitalized"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'rule-name-prefix-fail | '.", "fingerprint": "21702514f2124cfd6c0e986cdc04291c853d6b16d83b649147ffc30dab89832d", "location": {"path": "examples/playbooks/tasks/rule-name-prefix-fail.yml", "lines": {"begin": 5}}, "content": {"body": "Task/Handler: This is missing the prefix"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'rule-name-prefix-fail | '.", "fingerprint": "f915f8884bcaf085d5b6903a4213a2b7eb0f48530070a53e221c840e13604e81", "location": {"path": "examples/playbooks/tasks/rule-name-prefix-fail.yml", "lines": {"begin": 8}}, "content": {"body": "Task/Handler: name | This prefix is incomplete"}}, {"type": "issue", "check_name": "fqcn[action-core]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/fqcn/", "severity": "major", "description": "Use FQCN for builtin module actions (debug).", "fingerprint": "a95a5bf3e345af2247fd1e52250f96796db2d6ab4956eb25f3c4d933890d6c8c", "location": {"path": "examples/playbooks/tasks/varset.yml", "lines": {"begin": 2}}, "content": {"body": "Use `ansible.builtin.debug` or `ansible.legacy.debug` instead."}}, {"type": "issue", "check_name": "name[missing]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "All tasks should be named.", "fingerprint": "eaba8cef37866c609d326dedeef5c23208715136338356f7451bb878aeb9f913", "location": {"path": "examples/playbooks/tasks/varset.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: debug msg=var was set"}}, {"type": "issue", "check_name": "no-free-form", "categories": ["syntax", "risk"], "url": "https://docs.ansible.com/projects/lint/rules/no-free-form/", "severity": "major", "description": "Avoid using free-form when calling module actions. (debug)", "fingerprint": "9326a27a65ddf460509abaadde55fbb094b147055c7a724777dc3e7841a3cf34", "location": {"path": "examples/playbooks/tasks/varset.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: debug msg=var was set"}}, {"type": "issue", "check_name": "fqcn[action-core]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/fqcn/", "severity": "major", "description": "Use FQCN for builtin module actions (git).", "fingerprint": "bcb74d279f38da6c7ce6d0e114b33615a8a56415a10e21b22ee0566992258fc5", "location": {"path": "examples/playbooks/tasks/varset.yml", "lines": {"begin": 4}}, "content": {"body": "Use `ansible.builtin.git` or `ansible.legacy.git` instead."}}, {"type": "issue", "check_name": "latest[git]", "categories": ["idempotency"], "url": "https://docs.ansible.com/projects/lint/rules/latest/", "severity": "major", "description": "Result of the command may vary on subsequent runs.", "fingerprint": "7e898690e66cfa462cf9c5ea0483c694624a9efbfe8add30e68e90a6c0695c3c", "location": {"path": "examples/playbooks/tasks/varset.yml", "lines": {"begin": 4}}, "content": {"body": "Task/Handler: git repo=hello.git"}}, {"type": "issue", "check_name": "name[missing]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "All tasks should be named.", "fingerprint": "f6d8e2eb8e087f4caceedf75fca36e09e9c586b5d11af9f32881b14a24263c77", "location": {"path": "examples/playbooks/tasks/varset.yml", "lines": {"begin": 4}}, "content": {"body": "Task/Handler: git repo=hello.git"}}, {"type": "issue", "check_name": "no-free-form", "categories": ["syntax", "risk"], "url": "https://docs.ansible.com/projects/lint/rules/no-free-form/", "severity": "major", "description": "Avoid using free-form when calling module actions. (git)", "fingerprint": "2ec5260bbffc1f79d8ee11bb21e9074c85e7ccc40be05e1bcbb4ff9d76620f3c", "location": {"path": "examples/playbooks/tasks/varset.yml", "lines": {"begin": 4}}, "content": {"body": "Task/Handler: git repo=hello.git"}}, {"type": "issue", "check_name": "fqcn[action-core]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/fqcn/", "severity": "major", "description": "Use FQCN for builtin module actions (debug).", "fingerprint": "a15f23ae45bce26c1a1d91e59ae4c14cefa1fb358d5100499df9833a65088b55", "location": {"path": "examples/playbooks/tasks/varunset.yml", "lines": {"begin": 2}}, "content": {"body": "Use `ansible.builtin.debug` or `ansible.legacy.debug` instead."}}, {"type": "issue", "check_name": "name[missing]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "All tasks should be named.", "fingerprint": "7d7651fd5cb84b4a0d27769626201e8e9e58fe993b265d345d685f6244f8723f", "location": {"path": "examples/playbooks/tasks/varunset.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: debug msg=var was not set"}}, {"type": "issue", "check_name": "no-free-form", "categories": ["syntax", "risk"], "url": "https://docs.ansible.com/projects/lint/rules/no-free-form/", "severity": "major", "description": "Avoid using free-form when calling module actions. (debug)", "fingerprint": "aa6ed08b2a05a6803c878d68236e6d23ece9440bab8854541a18c1b70d39c750", "location": {"path": "examples/playbooks/tasks/varunset.yml", "lines": {"begin": 2}}, "content": {"body": "Task/Handler: debug msg=var was not set"}}, {"type": "issue", "check_name": "schema[tasks]", "categories": ["core"], "url": "https://docs.ansible.com/projects/lint/rules/schema/", "severity": "major", "description": "$[0] None is not of type 'object'", "fingerprint": "f1e1eb13c4403e66a139001294f6d9b1e202332c415e556b3e12e531eac0bc03", "location": {"path": "examples/playbooks/tasks/x.yml", "lines": {"begin": 1}}, "content": {"body": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}}, {"type": "issue", "check_name": "name[prefix]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/name/", "severity": "major", "description": "Task name should start with 'x | '.", "fingerprint": "0c18e154299073add69f912f24dd6ce58db7911b52eccc9ffacfbd8cadd96b20", "location": {"path": "examples/playbooks/tasks/x.yml", "lines": {"begin": 3}}, "content": {"body": "Task/Handler: Test include"}}, {"type": "issue", "check_name": "yaml[trailing-spaces]", "categories": ["formatting", "yaml"], "url": "https://docs.ansible.com/projects/lint/rules/yaml/", "severity": "major", "description": "Trailing spaces", "fingerprint": "c6836bfb3b0a9d43213ac3fcb3f183acf3fe42aa8070f68666571c2d8b56e72d", "location": {"path": "examples/playbooks/vars/empty.transformed.yml", "lines": {"begin": 1}}}, {"type": "issue", "check_name": "yaml[trailing-spaces]", "categories": ["formatting", "yaml"], "url": "https://docs.ansible.com/projects/lint/rules/yaml/", "severity": "major", "description": "Trailing spaces", "fingerprint": "70fdcf8887dc8e16b056e9c02c2b4afd5e9f8c5c337acdc280242454a8f75bab", "location": {"path": "examples/playbooks/vars/empty.yml", "lines": {"begin": 1}}}, {"type": "issue", "check_name": "schema[vars]", "categories": ["core"], "url": "https://docs.ansible.com/projects/lint/rules/schema/", "severity": "major", "description": "$ '123' does not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'. See https://docs.ansible.org.cn/ansible/latest/playbook_guide/playbooks_variables.html", "fingerprint": "ce028a186852938584cac57301aad952acc38d97f020b69c6d2591a24a53894e", "location": {"path": "examples/playbooks/vars/invalid_vars_schema.yml", "lines": {"begin": 1}}, "content": {"body": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}}, {"type": "issue", "check_name": "jinja[spacing]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/jinja/", "severity": "major", "description": "Jinja2 spacing could be improved: {{bad_format}} -> {{ bad_format }}", "fingerprint": "62efd54fdb23897a2932b5886c9a7c650fb42028adb309b7c3b9720bd90b0dc7", "location": {"path": "examples/playbooks/vars/jinja-spacing.yml", "lines": {"begin": 14}}, "content": {"body": "Jinja2 template rewrite recommendation: `{{ bad_format }}`."}}, {"type": "issue", "check_name": "jinja[spacing]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/jinja/", "severity": "major", "description": "Jinja2 spacing could be improved: Value: {{ bad_format}} -> Value: {{ bad_format }}", "fingerprint": "4b3b958ae78af83c14199d6493b7233b1e745bf7a12b96b1a0a8e9f72241d6c0", "location": {"path": "examples/playbooks/vars/jinja-spacing.yml", "lines": {"begin": 15}}, "content": {"body": "Jinja2 template rewrite recommendation: `Value: {{ bad_format }}`."}}, {"type": "issue", "check_name": "jinja[spacing]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/jinja/", "severity": "major", "description": "Jinja2 spacing could be improved: {{bad_format }} -> {{ bad_format }}", "fingerprint": "9bf6eb438c921e3c5cde419522ad5e6614aac009601cee4a0f996fe96a06795c", "location": {"path": "examples/playbooks/vars/jinja-spacing.yml", "lines": {"begin": 16}}, "content": {"body": "Jinja2 template rewrite recommendation: `{{ bad_format }}`."}}, {"type": "issue", "check_name": "jinja[spacing]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/jinja/", "severity": "major", "description": "Jinja2 spacing could be improved: {{ bad_format|filter }} -> {{ bad_format | filter }}", "fingerprint": "d5073967ee85abef3362f49b44cef42294659094dd634e7065044945b1cc7650", "location": {"path": "examples/playbooks/vars/jinja-spacing.yml", "lines": {"begin": 17}}, "content": {"body": "Jinja2 template rewrite recommendation: `{{ bad_format | filter }}`."}}, {"type": "issue", "check_name": "jinja[spacing]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/jinja/", "severity": "major", "description": "Jinja2 spacing could be improved: Value: {{ bad_format |filter }} -> Value: {{ bad_format | filter }}", "fingerprint": "eb63c490ac729ab0cfeb9fe140e8df91f9adc3c5156d354c823f6f053c9931a9", "location": {"path": "examples/playbooks/vars/jinja-spacing.yml", "lines": {"begin": 18}}, "content": {"body": "Jinja2 template rewrite recommendation: `Value: {{ bad_format | filter }}`."}}, {"type": "issue", "check_name": "jinja[spacing]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/jinja/", "severity": "major", "description": "Jinja2 spacing could be improved: {{ bad_format| filter }} -> {{ bad_format | filter }}", "fingerprint": "a7a17af9510e346bc22b2fd9055df4aebc86eee3ba2469ffadb48a819e26ad0f", "location": {"path": "examples/playbooks/vars/jinja-spacing.yml", "lines": {"begin": 19}}, "content": {"body": "Jinja2 template rewrite recommendation: `{{ bad_format | filter }}`."}}, {"type": "issue", "check_name": "jinja[spacing]", "categories": ["formatting"], "url": "https://docs.ansible.com/projects/lint/rules/jinja/", "severity": "major", "description": "Jinja2 spacing could be improved: {{ {'dummy_2': {'nested_dummy_1': 'value_1', 'nested_dummy_2': value_2}} | combine(dummy_1)}} -> {{ {'dummy_2': {'nested_dummy_1': 'value_1', 'nested_dummy_2': value_2}} | combine(dummy_1) }}", "fingerprint": "3b9cfd86d6b3497ecf387b1f9f2cff9d092538d12d564f4100344783f473f17b", "location": {"path": "examples/playbooks/vars/jinja-spacing.yml", "lines": {"begin": 32}}, "content": {"body": "Jinja2 template rewrite recommendation: `{{ {'dummy_2': {'nested_dummy_1': 'value_1', 'nested_dummy_2': value_2}} | combine(dummy_1) }}`."}}, {"type": "issue", "check_name": "schema[vars]", "categories": ["core"], "url": "https://docs.ansible.com/projects/lint/rules/schema/", "severity": "major", "description": "$ 'assert', 'hosts', \"{{ 'test_' }}var\", '\u00e9' do not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'. See https://docs.ansible.org.cn/ansible/latest/playbook_guide/playbooks_variables.html", "fingerprint": "d64b69f087a3edcde2a92e580237832f706f7b39a69000c758e85876b5173ea0", "location": {"path": "examples/playbooks/vars/rule_var_naming_fail.yml", "lines": {"begin": 1}}, "content": {"body": " Returned errors will not include exact line numbers, but they will mention\nthe schema name being used as a tag, like ``schema[playbook]``,\n``schema[tasks]``.\n\nThis rule is not skippable and stops further processing of the file.\n\nIf incorrect schema was picked, you might want to either:\n\n* move the file to standard location, so its file is detected correctly.\n* use ``kinds:`` option in linter config to help it pick correct file type.\n"}}, {"type": "issue", "check_name": "var-naming[pattern]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (CamelCaseIsBad) (vars: CamelCaseIsBad)", "fingerprint": "d751fc08b10223088db54853c453ca7629ade47886266bba83a87ad1cea125ec", "location": {"path": "examples/playbooks/vars/rule_var_naming_fail.yml", "lines": {"begin": 2}}}, {"type": "issue", "check_name": "var-naming[pattern]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (ALL_CAPS_ARE_BAD_TOO) (vars: ALL_CAPS_ARE_BAD_TOO)", "fingerprint": "08219e8a32755f781f7e21af544dbbb453a8c3a10dd6c4fc0d7ec28d62b10fc3", "location": {"path": "examples/playbooks/vars/rule_var_naming_fail.yml", "lines": {"begin": 6}}}, {"type": "issue", "check_name": "var-naming[no-keyword]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names must not be Python keywords. (assert) (vars: assert)", "fingerprint": "c39b111f4c477bcd3f7593f350a8d83c0cbaa35d6bb7ab78eab2837840209598", "location": {"path": "examples/playbooks/vars/rule_var_naming_fail.yml", "lines": {"begin": 10}}}, {"type": "issue", "check_name": "var-naming[non-ascii]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names must be ASCII. (\u00e9) (vars: \u00e9)", "fingerprint": "20f96eb5cbfa7b7c0ea68896b26c256e90c33bdfe98b789bf2aaf7d90bf8cfcd", "location": {"path": "examples/playbooks/vars/rule_var_naming_fail.yml", "lines": {"begin": 11}}}, {"type": "issue", "check_name": "var-naming[no-reserved]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names must not be Ansible reserved names. (hosts) (vars: hosts)", "fingerprint": "f4db6d957b256c9dfab86d706769f882dc491c533792ad1ae0d8d53a390b2f6c", "location": {"path": "examples/playbooks/vars/rule_var_naming_fail.yml", "lines": {"begin": 12}}}, {"type": "issue", "check_name": "var-naming[read-only]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "This special variable is read-only. (role_name) (vars: role_name)", "fingerprint": "ca1d9b623cedae38776fdde1c119aceff37fdef0ee8290b467d386114f56cd86", "location": {"path": "examples/playbooks/vars/rule_var_naming_fail.yml", "lines": {"begin": 13}}}, {"type": "issue", "check_name": "var-naming[pattern]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (CamelCaseIsBad) (vars: CamelCaseIsBad)", "fingerprint": "a206f2f07542fee336971e3ee0a28b35cfc1c827e613187afecb23c07d9c942a", "location": {"path": "examples/playbooks/vars/rule_var_naming_fails_files/bar.yml", "lines": {"begin": 2}}}, {"type": "issue", "check_name": "var-naming[pattern]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (ALL_CAPS_ARE_BAD_TOO) (vars: ALL_CAPS_ARE_BAD_TOO)", "fingerprint": "32283c12ed2b4bd96930ff1ae4427afdc9120a092f9ddc0f552f26580ff04e43", "location": {"path": "examples/playbooks/vars/rule_var_naming_fails_files/bar.yml", "lines": {"begin": 3}}}, {"type": "issue", "check_name": "var-naming[pattern]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (CamelCaseIsBad) (vars: CamelCaseIsBad)", "fingerprint": "103c2bf87b75c46689e6b2e3f52abc0d8145456ff657b19265be5cd6633e979f", "location": {"path": "examples/playbooks/vars/rule_var_naming_fails_files/foo.yml", "lines": {"begin": 2}}}, {"type": "issue", "check_name": "var-naming[pattern]", "categories": ["idiom"], "url": "https://docs.ansible.com/projects/lint/rules/var-naming/", "severity": "major", "description": "Variables names should match ^[a-z_][a-z0-9_]*$ regex. (ALL_CAPS_ARE_BAD_TOO) (vars: ALL_CAPS_ARE_BAD_TOO)", "fingerprint": "d25c074b8aa8e4b81a516cf7ce02b84b56713713264129cc48b35a51fe2bcaa6", "location": {"path": "examples/playbooks/vars/rule_var_naming_fails_files/foo.yml", "lines": {"begin": 3}}}, {"type": "issue", "check_name": "yaml[line-length]", "categories": ["formatting", "yaml"], "url": "https://docs.ansible.com/projects/lint/rules/yaml/", "severity": "major", "description": "Line too long (166 > 160 characters)", "fingerprint": "733abe54b4836a539898189154ced4ebd75dd9d5c8cbf6efd4b8becb2448b0f2", "location": {"path": "examples/playbooks/vars/strings.transformed.yml", "lines": {"begin": 8}}}, {"type": "issue", "check_name": "yaml[line-length]", "categories": ["formatting", "yaml"], "url": "https://docs.ansible.com/projects/lint/rules/yaml/", "severity": "major", "description": "Line too long (166 > 160 characters)", "fingerprint": "ac36a10857f393897986390c49c43e0da5efd0690ff9cb4abbbf2b7c3a204e14", "location": {"path": "examples/playbooks/vars/strings.transformed.yml", "lines": {"begin": 14}}}, {"type": "issue", "check_name": "yaml[hyphens]", "categories": ["formatting", "yaml"], "url": "https://docs.ansible.com/projects/lint/rules/yaml/", "severity": "major", "description": "Too many spaces after hyphen", "fingerprint": "560fef17da47f7e5827599fe6c52ecb9cea64ccef50a65b38ec67942fd00863f", "location": {"path": "examples/playbooks/vars/transform_nested_data.yml", "lines": {"begin": 3}}}, {"type": "issue", "check_name": "yaml[hyphens]", "categories": ["formatting", "yaml"], "url": "https://docs.ansible.com/projects/lint/rules/yaml/", "severity": "major", "description": "Too many spaces after hyphen", "fingerprint": "851c4e82d71171de0b62d0fae73e2b4f9f0ab4085d14d5579ab7de070548566d", "location": {"path": "examples/playbooks/vars/transform_nested_data.yml", "lines": {"begin": 6}}}, {"type": "issue", "check_name": "yaml[hyphens]", "categories": ["formatting", "yaml"], "url": "https://docs.ansible.com/projects/lint/rules/yaml/", "severity": "major", "description": "Too many spaces after hyphen", "fingerprint": "9f63928ccea82a2a5cc35defbbfe3ced42ca63af827b75cf198670d806bf0bad", "location": {"path": "examples/playbooks/vars/transform_nested_data.yml", "lines": {"begin": 7}}}]
历史上,-f json
用于生成 Code Climate JSON 报告,但在较新的版本中,我们将其含义改为 SARIF JSON 格式。
警告
如果可能,我们建议使用SARIF格式而不是 Code Climate 格式,因为 SARIF 格式更完整,具有完整的规范和 JSON 验证模式。Code Climate 格式不会公开我们的严重级别,因为我们使用该字段将警告映射为minor
问题,将错误映射为major
问题。
运行时指定规则¶
默认情况下,ansible-lint
应用在 ansible-lint/src/ansiblelint/rules
中找到的规则。使用 -r /path/to/custom-rules
选项指定自定义规则集的目录路径。对于多个自定义规则集,请使用单独的 -r
选项传递每个规则集。
您还可以使用 -R
选项以及一个或多个 -r
选项将默认规则与自定义规则结合使用。
包含带有标签的规则¶
每个规则都有一组一个或多个关联的标签。使用 -T
选项查看每个可用规则的标签列表。
然后,您可以使用 -t
选项指定标签,并将关联的规则包含在 lint 运行中。例如,以下 ansible-lint
命令仅应用与idempotency标签关联的规则:
$ ansible-lint -t idempotency playbook.yml
WARNING Skipped installing collection dependencies due to running in offline mode.
Passed: 0 failure(s), 0 warning(s) on 1 files. Last profile that met the validation criteria was 'production'.
以下显示了一组示例规则中可用的标签以及与每个标签关联的规则:
ansible-lint -T 2>/dev/null
# List of tags and rules they cover
command-shell: # Specific to use of command and shell modules
- risky-shell-pipe
core: # Related to internal implementation of the linter
- schema[ansible-lint-config]
- schema[ansible-navigator-config]
- schema[changelog]
- schema[execution-environment]
- schema[galaxy]
- schema[inventory]
- schema[meta-runtime]
- schema[meta]
- schema[molecule]
- schema[playbook]
- schema[requirements]
- schema[role-arg-spec]
- schema[rulebook]
- schema[tasks]
- schema[vars]
deprecations: # Indicate use of features that are removed from Ansible
- role-name[path]
experimental: # Newly introduced rules, by default triggering only warnings
- only-builtins
formatting: # Related to code-style
- risky-octal
idempotency: # Possible indication that consequent runs would produce different results
- package-latest
idiom: # Anti-pattern detected, likely to cause undesired behavior
- var-naming[no-jinja]
- var-naming[no-reserved]
- var-naming[pattern]
metadata: # Invalid metadata, likely related to galaxy, collections or roles
- role-name[path]
opt-in: # Rules that are not used unless manually added to `enable_list`
- only-builtins
risk:
- no-free-form[raw-non-string]
- no-free-form[raw]
security: # Rules related o potentially security issues, like exposing credentials
- no-log-password
syntax: # Related to wrong or deprecated syntax
- no-free-form[raw-non-string]
- no-free-form[raw]
unpredictability: # Warn about code that might not work in a predictable way
- risky-file-permissions
unskippable: # Indicate a fatal error that cannot be ignored or disabled
- syntax-check
yaml: # External linter which will also produce its own rule codes
- yaml[anchors]
- yaml[braces]
- yaml[brackets]
- yaml[colons]
- yaml[commas]
- yaml[comments-indentation]
- yaml[comments]
- yaml[document-end]
- yaml[document-start]
- yaml[empty-lines]
- yaml[empty-values]
- yaml[float-values]
- yaml[hyphens]
- yaml[indentation]
- yaml[key-duplicates]
- yaml[key-ordering]
- yaml[line-length]
- yaml[new-line-at-end-of-file]
- yaml[new-lines]
- yaml[octal-values]
- yaml[quoted-strings]
- yaml[trailing-spaces]
- yaml[truthy]
排除带有标签的规则¶
要按标识符或标签排除规则,请使用 -x SKIP_LIST
选项。例如,以下命令应用所有规则,除了带有formatting和metadata标签的规则:
忽略规则¶
要仅警告规则,请使用 -w WARN_LIST
选项。例如,以下命令仅显示与experimental
标签关联的规则的违规警告:
默认情况下,WARN_LIST
包含 ['experimental']
标签。如果您定义了自定义 WARN_LIST
,则必须添加 'experimental'
,以使 Ansible-lint 不会针对实验性规则失败。
忽略警告以避免误报¶
并非所有 lint 规则都精确,有些是一般性的经验规则。例如,高级git、yum或apt用法可能难以在 playbook 中实现。在这种情况下,Ansible-lint 可能会错误地触发规则违规。
要禁用特定任务的规则违规并忽略误报,请在行尾添加 # noqa: [rule_id]
。最好添加一个注释来说明为什么禁用了规则。
您可以将 # noqa: [rule_id]
注释添加到任务中任何行的末尾。您还可以使用空格分隔的列表跳过多个规则。
- name: This task would typically fire git-latest and partial-become rules
become_user: alice # noqa: git-latest partial-become
ansible.builtin.git: src=/path/to/git/repo dest=checkout
如果规则是基于行的,则 # noqa: [rule_id]
必须位于行尾。
- name: This would typically fire jinja[spacing]
get_url:
url: http://example.com/file.conf
dest: "{{dest_proj_path}}/foo.conf" # noqa: jinja[spacing]
如果您希望 Ansible-lint 完全跳过规则,请使用 -x
命令行参数或将其添加到配置中的 skip_list
中。
跳过规则最不推荐的方法是跳过任务的所有基于任务的规则,这不会跳过基于行的规则。例如,您可以对所有任务使用 skip_ansible_lint
标签:
- name: This would typically fire no-free-form
command: warn=no chmod 644 X
- name: This would typically fire git-latest
git: src=/path/to/git/repo dest=checkout
tags:
- skip_ansible_lint
应用配置文件¶
Ansible-lint 配置文件允许内容创建者逐步提高 Ansible playbook、角色和集合的质量。
在早期开发周期中,您需要 Ansible-lint 规则不太严格。从最小配置文件开始,确保 Ansible 可以加载您的内容。当您进入内容开发的下一个阶段时,您可以逐步应用配置文件以避免常见的缺陷和脆弱的复杂性。然后,当您准备好发布或共享您的内容时,您可以使用更严格规则的shared
和production
配置文件。这些配置文件增强了安全性,保证了可靠性,并确保您的 Ansible 内容易于他人贡献和使用。
注意
诸如opt-in
和experimental
之类的标签对直接或间接包含在配置文件中的规则无效。如果规则位于配置文件中,Ansible-lint 会将该规则应用于内容。
安装和配置ansible-lint
后,您可以按如下方式应用配置文件
- 使用
--list-profiles
标志查看可用的配置文件。
-
使用
--profile
参数指定配置文件,以使用这些规则检查您的内容,例如 -
使用
basic
配置文件强制执行标准样式和格式。
- 使用
safety
配置文件确保自动化的一致性、可靠性和安全性。
保险库¶
由于ansible-lint执行ansible,它也需要访问加密的密钥。如果您不提供对它们的访问权限,或者您担心安全隐患,您应该考虑重构您的代码,使其无需访问真实密钥即可进行代码检查。
- 配置在代码检查期间使用的虚拟回退值,这样Ansible就不会抱怨未定义的变量。
- 从代码检查过程中排除有问题的文件。
---
# Example of avoiding undefined variable error
foo: "{{ undefined_variable_name | default('dummy') }}"
请记住,即使您无法访问保险库,编写良好的剧本或角色也应该允许Ansible的语法检查通过。
在内部,ansible-lint会在每个剧本和角色上运行ansible-playbook --syntax-check
。由于ansible-code不支持直接对角色运行语法检查,因此代码检查工具将创建临时剧本,这些剧本仅包含项目中的每个角色。您需要更改角色的代码,使其在没有变量或参数的情况下调用时不会产生语法错误。这通常涉及使用defaults/
,但请确保您完全理解变量优先级。
依赖项和需求¶
Ansible-lint将识别用于运行时和测试目的的requirements.yml
文件并自动安装它们。这些文件的有效位置是
requirements.yml
roles/requirements.yml
collections/requirements.yml
tests/requirements.yml
tests/integration/requirements.yml
tests/unit/requirements.yml
galaxy.yml