Skip to content

Commit

Permalink
Handle bare exception case from nested jinja2 vars (#4315)
Browse files Browse the repository at this point in the history
  • Loading branch information
cavcrosby authored Sep 19, 2024
1 parent 242fea0 commit 9d63816
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
11 changes: 11 additions & 0 deletions examples/playbooks/jinja-nested-vars.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
- name: Test
gather_facts: false
hosts:
- localhost
tasks:
- name: Test
ansible.builtin.debug:
msg: "{{ cron_hour_raw }}"
vars:
cron_hour_raw: "{{ 12 | random(seed=inventory_hostname) }}"
42 changes: 38 additions & 4 deletions src/ansiblelint/rules/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
from ansiblelint.runner import get_matches
from ansiblelint.skip_utils import get_rule_skips_from_line
from ansiblelint.text import has_jinja
from ansiblelint.utils import parse_yaml_from_file, template
from ansiblelint.utils import ( # type: ignore[attr-defined]
Templar,
parse_yaml_from_file,
template,
)
from ansiblelint.yaml_utils import deannotate, nested_items_path

if TYPE_CHECKING:
Expand Down Expand Up @@ -95,7 +99,10 @@ class JinjaRule(AnsibleLintRule, TransformMixin):
tags = ["formatting"]
version_added = "v6.5.0"
_ansible_error_re = re.compile(
r"^(?P<error>.*): (?P<detail>.*)\. String: (?P<string>.*)$",
(
r"^(?P<error>.*): (?P<detail>.*)\. String: (?P<string>.*)$"
r"|An unhandled exception occurred while templating '.*'\. Error was a .*, original message: (?P<nested_error>.*)"
),
flags=re.MULTILINE,
)

Expand Down Expand Up @@ -160,13 +167,20 @@ def matchtask(
):
error = match.group("error")
detail = match.group("detail")
if error.startswith(
nested_error = match.group("nested_error")
if error and error.startswith(
"template error while templating string",
):
bypass = False
elif detail.startswith("unable to locate collection"):
elif detail and detail.startswith(
"unable to locate collection",
):
_logger.debug("Ignored AnsibleError: %s", exc)
bypass = True
elif nested_error and nested_error.startswith(
"Unexpected templating type error occurred on",
):
bypass = True
else:
bypass = False
elif re.match(r"^lookup plugin (.*) not found$", exc.message):
Expand Down Expand Up @@ -863,6 +877,26 @@ def test_jinja_transform(
assert expected_content == transformed_content
playbook.with_suffix(f".tmp{playbook.suffix}").unlink()

def test_jinja_nested_var_errors() -> None:
"""Tests our ability to handle nested var errors from jinja2 templates."""

def _do_template(*args, **kwargs): # type: ignore[no-untyped-def] # Templar.do_template has no type hint
data = args[1]

if data != "{{ 12 | random(seed=inventory_hostname) }}":
return do_template(*args, **kwargs)

msg = "Unexpected templating type error occurred on (foo): bar"
raise AnsibleError(msg)

do_template = Templar.do_template
collection = RulesCollection()
collection.register(JinjaRule())
lintable = Lintable("examples/playbooks/jinja-nested-vars.yml")
with mock.patch.object(Templar, "do_template", _do_template):
results = Runner(lintable, rules=collection).run()
assert len(results) == 0


def _get_error_line(task: dict[str, Any], path: list[str | int]) -> int:
"""Return error line number."""
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ setenv =
PRE_COMMIT_COLOR = always
# Number of expected test passes, safety measure for accidental skip of
# tests. Update value if you add/remove tests. (tox-extra)
PYTEST_REQPASS = 892
PYTEST_REQPASS = 893
FORCE_COLOR = 1
pre: PIP_PRE = 1
allowlist_externals =
Expand Down

0 comments on commit 9d63816

Please sign in to comment.