Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .ansible-lint
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ mock_roles:
# Enable checking of loop variable prefixes in roles
loop_var_prefix: "^(__|{role}_)"

# Enforce role-related variable names to start with the pattern below.
# By default Ansible Lint accepts "role name" prefix with optional leading underscore(s).
# With this option for example you can prefix role variables with the collection name
# which the role belongs to instead of role name.
role_var_prefix: "^_*{role}_"

# Enforce variable names to follow pattern below, in addition to Ansible own
# requirements, like avoiding python identifiers. To disable add `var-naming`
# to skip_list.
Expand Down
2 changes: 2 additions & 0 deletions examples/roles/role_vars_prefix_detection/.ansible-lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
role_var_prefix: "^_*({role}_|fo|bar)"
1 change: 1 addition & 0 deletions src/ansiblelint/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class Options: # pylint: disable=too-many-instance-attributes
# Refer to https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix
_default_supported = ["2.15.", "2.16.", "2.17.", "2.18.", "2.19."]
supported_ansible_also: list[str] = field(default_factory=list)
role_var_prefix: str | None = None

@property
def nodeps(self) -> bool:
Expand Down
9 changes: 3 additions & 6 deletions src/ansiblelint/rules/var_naming.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,9 @@ Possible errors messages:
!!! note

When using `include_role` or `import_role` with `vars`, vars should start
with included role name prefix. As this role might not be compliant
with this rule yet, you might need to temporarily disable this rule using
a `# noqa: var-naming[no-role-prefix]` comment.

In all other task types variable names defined in `vars` are considered
task-scoped and do not require the role prefix.
with included role name prefix. If you want to tweak the role vars'
prefix pattern such as prefixing them with the collection name, you could
use `role_var_prefix` configuration option.

## Settings

Expand Down
29 changes: 20 additions & 9 deletions src/ansiblelint/rules/var_naming.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
from ansible.vars.reserved import get_reserved_names

from ansiblelint.config import Options, options
from ansiblelint.constants import (
ANNOTATION_KEYS,
PLAYBOOK_ROLE_KEYWORDS,
RC,
)
from ansiblelint.constants import ANNOTATION_KEYS, PLAYBOOK_ROLE_KEYWORDS, RC
from ansiblelint.file_utils import Lintable
from ansiblelint.rules import AnsibleLintRule, RulesCollection
from ansiblelint.runner import Runner
Expand Down Expand Up @@ -44,6 +40,7 @@ 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)
re_role_var_prefix_pattern_str = options.role_var_prefix or "^_*{role}_"
reserved_names = get_reserved_names()
# List of special variables that should be treated as read-only. This list
# does not include connection variables, which we expect users to tune in
Expand Down Expand Up @@ -178,13 +175,16 @@ def get_var_naming_matcherror(

if (
prefix
and not ident.lstrip("_").startswith(f"{prefix.value}_")
and not re.match(
self.re_role_var_prefix_pattern_str.format(role=prefix.value),
ident,
)
and not has_jinja(prefix.value)
and is_fqcn_or_name(prefix.value)
):
return self.create_matcherror(
tag="var-naming[no-role-prefix]",
message=f"Variables names from within roles should use {prefix.value}_ as a prefix.",
message=f"Variables names from within roles should use /{self.re_role_var_prefix_pattern_str.format(role=prefix.value)}/ pattern as a prefix.",
filename=file,
data=ident,
)
Expand Down Expand Up @@ -346,8 +346,8 @@ def _parse_prefix(self, fqcn: str) -> Prefix:
if "pytest" in sys.modules:
import pytest

from ansiblelint.testing import ( # pylint: disable=ungrouped-imports
run_ansible_lint,
from ansiblelint.testing import (
run_ansible_lint, # pylint: disable=ungrouped-imports
)

@pytest.mark.parametrize(
Expand Down Expand Up @@ -430,6 +430,17 @@ def test_var_naming_with_role_prefix(
for result in results:
assert result.tag == "var-naming[no-role-prefix]"

def test_var_naming_with_custom_role_prefix() -> None:
"""Test rule matches."""
role_path = "examples/roles/role_vars_prefix_detection"
conf_path = "examples/roles/role_vars_prefix_detection/.ansible-lint"
result = run_ansible_lint(
f"--config-file={conf_path}",
role_path,
)
assert result.returncode == RC.SUCCESS
assert "var-naming[no-role-prefix]" not in result.stdout

@pytest.mark.libyaml
def test_var_naming_with_role_prefix_plays(
default_rules_collection: RulesCollection,
Expand Down
4 changes: 4 additions & 0 deletions src/ansiblelint/schemas/ansible-lint-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@
"title": "Quiet",
"type": "boolean"
},
"role_var_prefix": {
"title": "Role Var Prefix",
"type": "string"
},
"rules": {
"additionalProperties": {
"$ref": "#/$defs/rule"
Expand Down
6 changes: 2 additions & 4 deletions test/test_cli_role_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,6 @@ def test_run_role_identified_prefix_missing(local_test_dir: Path) -> None:
)
assert result.returncode == RC.VIOLATIONS_FOUND
assert (
"Variables names from within roles should use bar_ as a prefix" in result.stdout
)
assert (
"Variables names from within roles should use bar_ as a prefix" in result.stdout
"Variables names from within roles should use /^_*bar_/ pattern as a prefix."
in result.stdout
)
Loading