Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add optional rule to check for loop var prefix
Based on original custom rule written by Albin Vass on https://opendev.org/zuul/zuul-jobs/blame/branch/master/.rules/ZuulJobsNamespaceLoopVar.py This new rule becomes active only when loop_var_prefix is defined inside the config and allows user to use dynamic prefix based on role folder name.
- Loading branch information
Showing
12 changed files
with
208 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,35 @@ | ||
# .ansible-lint | ||
exclude_paths: | ||
- .github/ | ||
# parseable: true | ||
# quiet: true | ||
# verbosity: 1 | ||
|
||
# Mock modules or roles in order to pass ansible-playbook --syntax-check | ||
mock_modules: | ||
- zuul_return | ||
mock_roles: | ||
- mocked_role | ||
|
||
# Enable checking of loop variable prefixes in roles | ||
loop_var_prefix: "{role}_" | ||
|
||
use_default_rules: true | ||
# Load custom rules from this specific folder | ||
# rulesdir: | ||
# - ./rule/directory/ | ||
|
||
# This makes linter to fully ignore rules/tags listed below | ||
skip_list: | ||
- skip_this_tag | ||
- '401' | ||
|
||
# Report only a subset of tags and fully ignore any others | ||
# tags: | ||
# - '206' | ||
|
||
# This makes the linter display but not fail for rules/tags listed below: | ||
warn_list: | ||
- skip_this_tag | ||
- '401' | ||
- experimetal # experimental is included in the implicit list |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
- hosts: localhost | ||
tasks: | ||
# validate that we did not trigger loop-var-prefix on playbooks | ||
- name: that should pass | ||
debug: | ||
var: item | ||
loop: | ||
- foo | ||
- bar | ||
- name: a block | ||
block: | ||
- name: that should also pass | ||
debug: | ||
var: item | ||
loop: | ||
- apples | ||
- oranges |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# 3 expected no-loop-var-prefix failures at 2, 8, 18 | ||
- name: that should trigger no-loop-var-prefix | ||
debug: | ||
var: item | ||
loop: | ||
- foo | ||
- bar | ||
- name: that should fail due to wrong custom | ||
debug: | ||
var: zz_item | ||
loop: | ||
- foo | ||
- bar | ||
loop_control: | ||
loop_var: zz_item | ||
- name: Using a block | ||
block: | ||
- name: that should also not pass | ||
debug: | ||
var: item | ||
loop: | ||
- apples | ||
- oranges |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,5 +38,6 @@ | |
warn_list=[], | ||
kinds=DEFAULT_KINDS, | ||
mock_modules=[], | ||
mock_roles=[] | ||
mock_roles=[], | ||
loop_var_prefix=None | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
"""Optional Ansible-lint rule to enforce use of prefix on role loop vars.""" | ||
from typing import TYPE_CHECKING, List | ||
|
||
from ansiblelint.config import options | ||
from ansiblelint.errors import MatchError | ||
from ansiblelint.file_utils import Lintable | ||
from ansiblelint.rules import AnsibleLintRule | ||
from ansiblelint.text import toidentifier | ||
|
||
if TYPE_CHECKING: | ||
from typing import Any | ||
|
||
from ansiblelint.constants import odict | ||
|
||
|
||
class RoleLoopVarPrefix(AnsibleLintRule): | ||
"""Role loop_var should use configured prefix.""" | ||
|
||
id = 'no-loop-var-prefix' | ||
shortdesc = __doc__ | ||
link = ( | ||
"https://docs.ansible.com/ansible/latest/user_guide/" | ||
"playbooks_loops.html#defining-inner-and-outer-variable-names-with-loop-var") | ||
description = """\ | ||
Looping inside roles has the risk of clashing with loops from user-playbooks.\ | ||
""" | ||
|
||
tags = ['no-loop-var-prefix', 'safety'] | ||
prefix = "" | ||
severity = 'MEDIUM' | ||
|
||
def matchplay( | ||
self, | ||
file: Lintable, | ||
data: "odict[str, Any]") -> List[MatchError]: | ||
"""Return matches found for a specific playbook.""" | ||
results: List[MatchError] = [] | ||
|
||
if not options.loop_var_prefix: | ||
return results | ||
self.prefix = options.loop_var_prefix.format(role=toidentifier(file.role)) | ||
self.shortdesc = f"{self.__class__.shortdesc}: {self.prefix}" | ||
|
||
if file.kind not in ('tasks', 'handlers'): | ||
return results | ||
|
||
results.extend(self.handle_play(file, data)) | ||
return results | ||
|
||
def handle_play( | ||
self, | ||
lintable: Lintable, | ||
task: "odict[str, Any]") -> List[MatchError]: | ||
"""Return matches for a playlist.""" | ||
results = [] | ||
if 'block' in task: | ||
results.extend(self.handle_tasks(lintable, task['block'])) | ||
else: | ||
results.extend(self.handle_task(lintable, task)) | ||
return results | ||
|
||
def handle_tasks( | ||
self, | ||
lintable: Lintable, | ||
tasks: List["odict[str, Any]"]) -> List[MatchError]: | ||
"""Return matches for a list of tasks.""" | ||
results = [] | ||
for play in tasks: | ||
results.extend(self.handle_play(lintable, play)) | ||
return results | ||
|
||
def handle_task( | ||
self, | ||
lintable: Lintable, | ||
task: "odict[str, Any]") -> List[MatchError]: | ||
"""Return matches for a specific task.""" | ||
results = [] | ||
has_loop = 'loop' in task | ||
for key in task.keys(): | ||
if key.startswith('with_'): | ||
has_loop = True | ||
|
||
if has_loop: | ||
loop_control = task.get('loop_control', {}) | ||
loop_var = loop_control.get('loop_var', "") | ||
|
||
if not loop_var or not loop_var.startswith(self.prefix): | ||
results.append( | ||
self.create_matcherror( | ||
filename=lintable, | ||
linenumber=task['__line__'] | ||
)) | ||
return results |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters