add new rule check_filter_separation

This commit is contained in:
Robert Kaussow 2019-01-30 00:27:30 +01:00
parent 86ffffd8e1
commit 098366fcf8
3 changed files with 77 additions and 42 deletions

View File

@ -18,20 +18,22 @@ The project name is an acronym for **L**ovely **A**utomation **TE**sting f**R**m
## Table of Content ## Table of Content
- [Setup](#setup) - [ansible-later](#ansible-later)
- [Using pip](#using-pip) - [Table of Content](#table-of-content)
- [From source](#from-source) - [Setup](#setup)
- [Usage](#usage) - [Using pip](#using-pip)
- [Configuration](#configuration) - [From source](#from-source)
- [Review a git repositories](#review-a-git-repositories) - [Usage](#usage)
- [Review a list of files](#review-a-list-of-files) - [Configuration](#configuration)
- [Buildin rules](#buildin-rules) - [Review a git repositories](#review-a-git-repositories)
- [Build your own](#build-your-own) - [Review a list of files](#review-a-list-of-files)
- [The standards file](#the-standards-file) - [Buildin rules](#buildin-rules)
- [Candidates](#candidates) - [Build your own](#build-your-own)
- [Minimal standards checks](#minimal-standards-checks) - [The standards file](#the-standards-file)
- [License](#license) - [Candidates](#candidates)
- [Maintainers and Contributors](#maintainers-and-contributors) - [Minimal standards checks](#minimal-standards-checks)
- [License](#license)
- [Maintainers and Contributors](#maintainers-and-contributors)
--- ---
@ -130,31 +132,32 @@ The standards directory can be overridden with the `-d` argument.
Reviews are nothing without some rules or standards against which to review. ansible-later Reviews are nothing without some rules or standards against which to review. ansible-later
comes with a couple of built-in checks explained in the following table. comes with a couple of built-in checks explained in the following table.
| Rule | ID | Description | Parameter | | Rule | ID | Description | Parameter |
| ------------------------------- | ----------- | ---------------------------------------------------------------- | -------------------------------------------------------------------- | |---------------------------------|-------------|-------------------------------------------------------------------|----------------------------------------------------------------------|
| check_yaml_empty_lines | LINT0001 | YAML should not contain unnecessarily empty lines. | {max: 1, max-start: 0, max-end: 0} | | check_yaml_empty_lines | LINT0001 | YAML should not contain unnecessarily empty lines. | {max: 1, max-start: 0, max-end: 0} |
| check_yaml_indent | LINT0002 | YAML should be correctly indented. | {spaces: 2, check-multi-line-strings: false, indent-sequences: true} | | check_yaml_indent | LINT0002 | YAML should be correctly indented. | {spaces: 2, check-multi-line-strings: false, indent-sequences: true} |
| check_yaml_hyphens | LINT0003 | YAML should use consitent number of spaces after hyphens (-). | {max-spaces-after: 1} | | check_yaml_hyphens | LINT0003 | YAML should use consitent number of spaces after hyphens (-). | {max-spaces-after: 1} |
| check_yaml_document_start | LINT0004 | YAML should contain document start marker. | {document-start: {present: true}} | | check_yaml_document_start | LINT0004 | YAML should contain document start marker. | {document-start: {present: true}} |
| check_yaml_colons | LINT0005 | YAML should use consitent number of spaces around colons. | {colons: {max-spaces-before: 0, max-spaces-after: 1}} | | check_yaml_colons | LINT0005 | YAML should use consitent number of spaces around colons. | {colons: {max-spaces-before: 0, max-spaces-after: 1}} |
| check_yaml_file | LINT0006 | Roles file should be in yaml format. | | | check_yaml_file | LINT0006 | Roles file should be in yaml format. | |
| check_yaml_has_content | LINT0007 | Files should contain useful content. | | | check_yaml_has_content | LINT0007 | Files should contain useful content. | |
| check_native_yaml | LINT0008 | Use YAML format for tasks and handlers rather than key=value. | | | check_native_yaml | LINT0008 | Use YAML format for tasks and handlers rather than key=value. | |
| check_line_between_tasks | ANSIBLE0001 | Single tasks should be separated by an empty line. | | | check_line_between_tasks | ANSIBLE0001 | Single tasks should be separated by an empty line. | |
| check_meta_main | ANSIBLE0002 | Meta file should contain a basic subset of parameters. | author, description, min_ansible_version, platforms, dependencies | | check_meta_main | ANSIBLE0002 | Meta file should contain a basic subset of parameters. | author, description, min_ansible_version, platforms, dependencies |
| check_unique_named_task | ANSIBLE0003 | Tasks and handlers must be uniquely named within a file. | | | check_unique_named_task | ANSIBLE0003 | Tasks and handlers must be uniquely named within a file. | |
| check_braces | ANSIBLE0004 | YAML should use consitent number of spaces around variables. | | | check_braces | ANSIBLE0004 | YAML should use consitent number of spaces around variables. | |
| check_scm_in_src | ANSIBLE0005 | Use scm key rather than src: scm+url in requirements file. | | | check_scm_in_src | ANSIBLE0005 | Use scm key rather than src: scm+url in requirements file. | |
| check_named_task | ANSIBLE0006 | Tasks and handlers must be named. | excludes: meta, debug, include\_\*, import\_\*, block | | check_named_task | ANSIBLE0006 | Tasks and handlers must be named. | excludes: meta, debug, include\_\*, import\_\*, block |
| check_name_format | ANSIBLE0007 | Name of tasks and handlers must be formatted. | formats: first letter capital | | check_name_format | ANSIBLE0007 | Name of tasks and handlers must be formatted. | formats: first letter capital |
| check_command_instead_of_module | ANSIBLE0008 | Commands should not be used in place of modules. | | | check_command_instead_of_module | ANSIBLE0008 | Commands should not be used in place of modules. | |
| check_install_use_latest | ANSIBLE0009 | Package managers should not install with state=latest. | | | check_install_use_latest | ANSIBLE0009 | Package managers should not install with state=latest. | |
| check_shell_instead_command | ANSIBLE0010 | Use Shell only when piping, redirecting or chaining commands. | | | check_shell_instead_command | ANSIBLE0010 | Use Shell only when piping, redirecting or chaining commands. | |
| check_command_has_changes | ANSIBLE0011 | Commands should be idempotent and only used with some checks. | | | check_command_has_changes | ANSIBLE0011 | Commands should be idempotent and only used with some checks. | |
| check_empty_string_compare | ANSIBLE0012 | Don't compare to "" - use `when: var` or `when: not var` | | | check_empty_string_compare | ANSIBLE0012 | Don't compare to "" - use `when: var` or `when: not var`. | |
| check_compare_to_literal_bool | ANSIBLE0013 | Don't compare to True/False - use `when: var` or `when: not var` | | | check_compare_to_literal_bool | ANSIBLE0013 | Don't compare to True/False - use `when: var` or `when: not var`. | |
| check_literal_bool_format | ANSIBLE0014 | Literal bools should be written as `True/False` or `yes/no` | forbidden values are `true false TRUE FALSE Yes No YES NO` | | check_literal_bool_format | ANSIBLE0014 | Literal bools should be written as `True/False` or `yes/no`. | forbidden values are `true false TRUE FALSE Yes No YES NO` |
| check_become_user | ANSIBLE0015 | `become` should be always used combined with `become_user` | | | check_become_user | ANSIBLE0015 | `become` should be always used combined with `become_user`. | |
| check_filter_separation | ANSIBLE0016 | Jinja2 filters should be separated with spaces. | |
### Build your own ### Build your own
@ -217,7 +220,7 @@ Each file passed to `ansible-later` will be classified. The result is a `Candida
which contains some meta informations and is an instance of one of following object types. which contains some meta informations and is an instance of one of following object types.
| Object type | Description | | Object type | Description |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------- | |-------------|------------------------------------------------------------------------------------------------------------------------------|
| Task | all files within the parent dir `tasks` | | Task | all files within the parent dir `tasks` |
| Handler | all files within the parent dir `handler` | | Handler | all files within the parent dir `handler` |
| RoleVars | all files within the parent dir `vars` or `default` | | RoleVars | all files within the parent dir `vars` or `default` |

View File

@ -23,6 +23,7 @@ from ansiblelater.rules.ansiblefiles import check_empty_string_compare
from ansiblelater.rules.ansiblefiles import check_compare_to_literal_bool from ansiblelater.rules.ansiblefiles import check_compare_to_literal_bool
from ansiblelater.rules.ansiblefiles import check_literal_bool_format from ansiblelater.rules.ansiblefiles import check_literal_bool_format
from ansiblelater.rules.ansiblefiles import check_become_user from ansiblelater.rules.ansiblefiles import check_become_user
from ansiblelater.rules.ansiblefiles import check_filter_separation
tasks_should_be_separated = Standard(dict( tasks_should_be_separated = Standard(dict(
@ -133,8 +134,8 @@ literal_bool_should_be_formatted = Standard(dict(
name="Literal bools should start with a capital letter", name="Literal bools should start with a capital letter",
check=check_literal_bool_format, check=check_literal_bool_format,
version="0.1", version="0.1",
types=[["playbook", "task", "handler", "rolevars", types=["playbook", "task", "handler", "rolevars",
"hostvars", "groupvars"]] "hostvars", "groupvars"]
)) ))
use_become_with_become_user = Standard(dict( use_become_with_become_user = Standard(dict(
@ -145,6 +146,15 @@ use_become_with_become_user = Standard(dict(
types=["playbook", "task", "handler"] types=["playbook", "task", "handler"]
)) ))
use_spaces_around_filters = Standard(dict(
id="ANSIBLE0016",
name="jinja2 filters should be separated with spaces",
check=check_filter_separation,
version="0.1",
types=["playbook", "task", "handler", "rolevars",
"hostvars", "groupvars"]
))
files_should_not_contain_unnecessarily_empty_lines = Standard(dict( files_should_not_contain_unnecessarily_empty_lines = Standard(dict(
id="LINT0001", id="LINT0001",
name="YAML should not contain unnecessarily empty lines", name="YAML should not contain unnecessarily empty lines",
@ -236,6 +246,7 @@ standards = [
dont_compare_to_literal_bool, dont_compare_to_literal_bool,
literal_bool_should_be_formatted, literal_bool_should_be_formatted,
use_become_with_become_user, use_become_with_become_user,
use_spaces_around_filters,
# Lint # Lint
files_should_not_contain_unnecessarily_empty_lines, files_should_not_contain_unnecessarily_empty_lines,
files_should_be_indented, files_should_be_indented,

View File

@ -231,3 +231,24 @@ def check_become_user(candidate, settings):
errors.append(Error(task["__line__"], description)) errors.append(Error(task["__line__"], description))
return Result(candidate.path, errors) return Result(candidate.path, errors)
def check_filter_separation(candidate, settings):
yamllines, errors = get_normalized_yaml(candidate, settings)
description = "no suitable numbers of spaces (required: 1)"
matches = []
braces = re.compile("{{(.*?)}}")
filters = re.compile(r"(?<=\|)([\s]{2,}[^\s}]+|[^\s]+)|([^\s{]+[\s]{2,}|[^\s]+)(?=\|)")
if not errors:
for i, line in yamllines:
match = braces.findall(line)
if match:
for item in match:
matches.append((i, item))
for i, line in matches:
if filters.findall(line):
errors.append(Error(i, description))
return Result(candidate.path, errors)