diff --git a/examples/playbooks/vars/rule_var_naming_fail.yml b/examples/playbooks/vars/rule_var_naming_fail.yml index e50b65e00e..24cd490614 100644 --- a/examples/playbooks/vars/rule_var_naming_fail.yml +++ b/examples/playbooks/vars/rule_var_naming_fail.yml @@ -6,5 +6,6 @@ this_is_valid: # valid because content is a dict, not a variable ALL_CAPS_ARE_BAD_TOO: ... # invalid "{{ 'test_' }}var": "value" # noqa: schema CamelCaseButErrorIgnored: true # noqa: var-naming -assert: true # invalid due to reserved keyword +assert: true # invalid due to being Python reserved keyword é: true # invalid due to non-ascii character +hosts: true # invalid as being Ansible reserved name diff --git a/src/ansiblelint/rules/var_naming.md b/src/ansiblelint/rules/var_naming.md index d588591c01..48b77be562 100644 --- a/src/ansiblelint/rules/var_naming.md +++ b/src/ansiblelint/rules/var_naming.md @@ -18,6 +18,7 @@ Possible errors messages: - `var-naming[pattern]`: Variables names should match ... regex. - `var-naming[no-role-prefix]`: Variables names from within roles should use `role_name_` as a prefix. +- `var-naming[no-reserved]`: Variables names must not be Ansible reserved names. ## Settings @@ -38,6 +39,7 @@ var_naming_pattern: "^[a-z_][a-z0-9_]*$" CamelCase: true # <- Contains a mix of lowercase and uppercase characters. ALL_CAPS: bar # <- Contains only uppercase characters. v@r!able: baz # <- Contains special characters. + hosts: [] # <- hosts is an Ansible reserved name ``` ## Correct Code @@ -50,6 +52,7 @@ var_naming_pattern: "^[a-z_][a-z0-9_]*$" lowercase: true # <- Contains only lowercase characters. no_caps: bar # <- Does not contains uppercase characters. variable: baz # <- Does not contain special characters. + my_hosts: [] # <- Does not use a reserved names. ``` [cop]: https://redhat-cop.github.io/automation-good-practices/#_naming_things diff --git a/src/ansiblelint/rules/var_naming.py b/src/ansiblelint/rules/var_naming.py index fc0eb98e24..1bafe20a63 100644 --- a/src/ansiblelint/rules/var_naming.py +++ b/src/ansiblelint/rules/var_naming.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any from ansible.parsing.yaml.objects import AnsibleUnicode +from ansible.vars.reserved import get_reserved_names from ansiblelint.config import options from ansiblelint.constants import LINE_NUMBER_KEY, RC @@ -31,8 +32,9 @@ class VariableNamingRule(AnsibleLintRule): needs_raw_task = True re_pattern_str = options.var_naming_pattern or "^[a-z_][a-z0-9_]*$" re_pattern = re.compile(re_pattern_str) + reserved_names = get_reserved_names() - # pylint: disable=too-many-return-statements) + # pylint: disable=too-many-return-statements def get_var_naming_matcherror( self, ident: str, @@ -52,14 +54,21 @@ def get_var_naming_matcherror( except UnicodeEncodeError: return MatchError( tag="var-naming[non-ascii]", - message="Variables names must be ASCII.", + message=f"Variables names must be ASCII. ({ident})", rule=self, ) if keyword.iskeyword(ident): return MatchError( tag="var-naming[no-keyword]", - message="Variables names must not be Python keywords.", + message=f"Variables names must not be Python keywords. ({ident})", + rule=self, + ) + + if ident in self.reserved_names: + return MatchError( + tag="var-naming[no-reserved]", + message=f"Variables names must not be Ansible reserved names. ({ident})", rule=self, ) @@ -74,7 +83,7 @@ def get_var_naming_matcherror( if not bool(self.re_pattern.match(ident)): return MatchError( tag="var-naming[pattern]", - message=f"Variables names should match {self.re_pattern_str} regex.", + message=f"Variables names should match {self.re_pattern_str} regex. ({ident})", rule=self, ) @@ -140,7 +149,6 @@ def matchtask( results.append(match_error) # If the task uses the 'set_fact' module - # breakpoint() ansible_module = task["action"]["__ansible_module__"] if ansible_module == "set_fact": for key in filter( @@ -239,6 +247,7 @@ def test_invalid_var_name_varsfile( ("var-naming[no-jinja]", 7), ("var-naming[no-keyword]", 9), ("var-naming[non-ascii]", 10), + ("var-naming[no-reserved]", 11), ) assert len(results) == len(expected_errors) for idx, result in enumerate(results): diff --git a/src/ansiblelint/runner.py b/src/ansiblelint/runner.py index 2cd3b38d52..8e1f068028 100644 --- a/src/ansiblelint/runner.py +++ b/src/ansiblelint/runner.py @@ -147,7 +147,6 @@ def run(self) -> list[MatchError]: ) else: filename = warn.source - # breakpoint() match = MatchError( message=warn.message if isinstance(warn.message, str)