From a4b10ad477d90dec9d71e4354f6de5083a7c23e0 Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Thu, 24 Nov 2022 01:08:43 +0000 Subject: [PATCH] Avoid Object of type PosixPath is not JSON serializable with jinja2 (#2724) Fixes: #2697 --- .config/dictionary.txt | 1 + examples/playbooks/rule-jinja-valid.yml | 20 ++++++++++++++++++++ src/ansiblelint/rules/jinja.py | 20 +++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/.config/dictionary.txt b/.config/dictionary.txt index d0fd76d7db..d8ed5386b7 100644 --- a/.config/dictionary.txt +++ b/.config/dictionary.txt @@ -74,6 +74,7 @@ createfile darglint dataclasses dbservers +deannotate debops decryptable delenv diff --git a/examples/playbooks/rule-jinja-valid.yml b/examples/playbooks/rule-jinja-valid.yml index 129ae1cdf0..00ce00f387 100644 --- a/examples/playbooks/rule-jinja-valid.yml +++ b/examples/playbooks/rule-jinja-valid.yml @@ -26,3 +26,23 @@ vars: ns_vars: {} x: "{{ lookup('ansible.builtin.template', 'namespace.yaml.j2', template_vars=ns_vars) | from_yaml }}" + +# https://github.com/ansible/ansible-lint/issues/2697 +- name: Test linter + hosts: localhost + gather_facts: false + tasks: + - name: Passed linter + ansible.builtin.debug: + msg: "{{ test | to_json }}" + vars: + test: + one: two + param: "{{ ansible_host }}" + - name: Failed linter + ansible.builtin.debug: + msg: "{{ test | to_json }}" + vars: + test: + one: two + param: no jinja diff --git a/src/ansiblelint/rules/jinja.py b/src/ansiblelint/rules/jinja.py index 8c953187d2..94e5a9e9aa 100644 --- a/src/ansiblelint/rules/jinja.py +++ b/src/ansiblelint/rules/jinja.py @@ -29,6 +29,24 @@ Token = namedtuple("Token", "lineno token_type value") +DEANNOTATE_KEYS = ("__file__", "__line__", "__start_line__", "__end_line__") + + +def deannotate(data: Any) -> Any: + """Remove our annotations like __file__ and __line__ and return a JSON serializable object.""" + if isinstance(data, dict): + result = data.copy() + for key, value in data.items(): + if key in DEANNOTATE_KEYS: + del result[key] + elif isinstance(value, list): + for i, item in enumerate(value): + value[i] = deannotate(item) + elif isinstance(value, dict): + result[key] = deannotate(value) + return result + return result + class JinjaRule(AnsibleLintRule): """Rule that looks inside jinja2 templates.""" @@ -62,7 +80,7 @@ def matchtask( # noqa: C901 template( basedir=file.dir if file else ".", value=v, - variables=task.get("vars", {}), + variables=deannotate(task.get("vars", {})), fail_on_error=True, # we later decide which ones to ignore or not ) # ValueError RepresenterError