From 098366fcf8e4cb259a1b159d5bb9243c70a64536 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Wed, 30 Jan 2019 00:27:30 +0100 Subject: [PATCH] add new rule check_filter_separation --- README.md | 83 ++++++++++++++++-------------- ansiblelater/examples/standards.py | 15 +++++- ansiblelater/rules/ansiblefiles.py | 21 ++++++++ 3 files changed, 77 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 37bf951..14cc5f5 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,22 @@ The project name is an acronym for **L**ovely **A**utomation **TE**sting f**R**m ## Table of Content -- [Setup](#setup) - - [Using pip](#using-pip) - - [From source](#from-source) -- [Usage](#usage) - - [Configuration](#configuration) - - [Review a git repositories](#review-a-git-repositories) - - [Review a list of files](#review-a-list-of-files) - - [Buildin rules](#buildin-rules) -- [Build your own](#build-your-own) - - [The standards file](#the-standards-file) - - [Candidates](#candidates) - - [Minimal standards checks](#minimal-standards-checks) -- [License](#license) -- [Maintainers and Contributors](#maintainers-and-contributors) +- [ansible-later](#ansible-later) + - [Table of Content](#table-of-content) + - [Setup](#setup) + - [Using pip](#using-pip) + - [From source](#from-source) + - [Usage](#usage) + - [Configuration](#configuration) + - [Review a git repositories](#review-a-git-repositories) + - [Review a list of files](#review-a-list-of-files) + - [Buildin rules](#buildin-rules) + - [Build your own](#build-your-own) + - [The standards file](#the-standards-file) + - [Candidates](#candidates) + - [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 comes with a couple of built-in checks explained in the following table. -| 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_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_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_file | LINT0006 | Roles file should be in yaml format. | | -| 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_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_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_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_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_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_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_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_become_user | ANSIBLE0015 | `become` should be always used combined with `become_user` | | +| 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_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_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_file | LINT0006 | Roles file should be in yaml format. | | +| 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_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_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_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_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_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_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_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_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 @@ -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. | Object type | Description | -| ----------- | ---------------------------------------------------------------------------------------------------------------------------- | +|-------------|------------------------------------------------------------------------------------------------------------------------------| | Task | all files within the parent dir `tasks` | | Handler | all files within the parent dir `handler` | | RoleVars | all files within the parent dir `vars` or `default` | diff --git a/ansiblelater/examples/standards.py b/ansiblelater/examples/standards.py index 0ac3e05..d7c5cb7 100644 --- a/ansiblelater/examples/standards.py +++ b/ansiblelater/examples/standards.py @@ -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_literal_bool_format from ansiblelater.rules.ansiblefiles import check_become_user +from ansiblelater.rules.ansiblefiles import check_filter_separation 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", check=check_literal_bool_format, version="0.1", - types=[["playbook", "task", "handler", "rolevars", - "hostvars", "groupvars"]] + types=["playbook", "task", "handler", "rolevars", + "hostvars", "groupvars"] )) use_become_with_become_user = Standard(dict( @@ -145,6 +146,15 @@ use_become_with_become_user = Standard(dict( 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( id="LINT0001", name="YAML should not contain unnecessarily empty lines", @@ -236,6 +246,7 @@ standards = [ dont_compare_to_literal_bool, literal_bool_should_be_formatted, use_become_with_become_user, + use_spaces_around_filters, # Lint files_should_not_contain_unnecessarily_empty_lines, files_should_be_indented, diff --git a/ansiblelater/rules/ansiblefiles.py b/ansiblelater/rules/ansiblefiles.py index 36b0964..c0aaa1f 100644 --- a/ansiblelater/rules/ansiblefiles.py +++ b/ansiblelater/rules/ansiblefiles.py @@ -231,3 +231,24 @@ def check_become_user(candidate, settings): errors.append(Error(task["__line__"], description)) 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)