diff --git a/ansiblelater/rules/CheckNestedJinja.py b/ansiblelater/rules/CheckNestedJinja.py new file mode 100644 index 0000000..4ced39a --- /dev/null +++ b/ansiblelater/rules/CheckNestedJinja.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Author: Adrián Tóth +# +# Copyright (c) 2020, Red Hat, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +import re + +from ansiblelater.standard import StandardBase + + +class CheckNestedJinja(StandardBase): + + sid = "ANSIBLE0023" + description = "Don't use nested Jinja2 pattern" + helptext = ( + "there should not be any nested jinja pattern " + "like `{{ list_one + {{ list_two | max }} }}`" + ) + version = "0.2" + types = ["playbook", "task", "handler", "rolevars", "hostvars", "groupvars"] + + def check(self, candidate, settings): + yamllines, errors = self.get_normalized_yaml(candidate, settings) + pattern = re.compile(r"{{(?:[^{}]*)?[^'\"]{{") + matches = [] + + if not errors: + for i, line in yamllines: + if "!unsafe" in line: + continue + + match = pattern.findall(line) + if match: + for item in match: + matches.append((i, item)) + + for i, line in matches: + errors.append(self.Error(i, self.helptext)) + + return self.Result(candidate.path, errors) diff --git a/docs/content/included_rules/_index.md b/docs/content/included_rules/_index.md index 5c74e05..8955731 100644 --- a/docs/content/included_rules/_index.md +++ b/docs/content/included_rules/_index.md @@ -37,3 +37,4 @@ Reviews are nothing without some rules or standards against which to review. ans | CheckGitHasVersion | ANSIBLE0020 | Git checkouts should use explicit version. | | | CheckMetaChangeFromDefault | ANSIBLE0021 | Roles meta/main.yml default values should be changed. | | | CheckWhenFormat | ANSIBLE0022 | Don't use Jinja2 in `when`. | | +| CheckNestedJinja | ANSIBLE0023 | Don't use nested Jinja2 pattern. | |