From c4e2f037768de9804f7ced792f343cfc17a06f9a Mon Sep 17 00:00:00 2001 From: Adam Romanek Date: Mon, 1 Feb 2021 20:24:50 +0100 Subject: [PATCH] Fix support for !j2-yaml tag on project level (missing deepcopy impl) The properties of 'project' objects are deepcopied in YamlParser._expandYamlForTemplateJob(), including any Jinja2YamlLoader objects produced by !j2-yaml tag. Because of the missing __deepcopy__() definition in Jinja2YamlLoader, the parent class' implementation was used, causing the deepcopied object be of Jinja2Loader type. Consequently the rendered value was always a string, not an instance of LateYamlLoader as it supposed to be. This change fixes the issue in Jinja2YamlLoader and potentially in LateYamlLoader, however the latter is currently not deepcopied anywhere so no test could be written to cover it. Change-Id: I24fda368a4af0e9aac7b78c478ac7b4eddf27b9b --- jenkins_jobs/local_yaml.py | 6 +++ .../fixtures/jinja-yaml04-deepcopy.xml | 38 +++++++++++++++++++ .../fixtures/jinja-yaml04-deepcopy.yaml | 28 ++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 tests/yamlparser/fixtures/jinja-yaml04-deepcopy.xml create mode 100644 tests/yamlparser/fixtures/jinja-yaml04-deepcopy.yaml diff --git a/jenkins_jobs/local_yaml.py b/jenkins_jobs/local_yaml.py index cece2eadb..e1b26bd1c 100644 --- a/jenkins_jobs/local_yaml.py +++ b/jenkins_jobs/local_yaml.py @@ -609,6 +609,9 @@ class LateYamlLoader(CustomLoader): self._yaml_str = yaml_str self._loader = loader + def __deepcopy__(self, memo): + return LateYamlLoader(self._yaml_str, copy.deepcopy(self._loader, memo)) + def get_object_to_format(self): return load(self._yaml_str, search_path=self._loader._search_path) @@ -618,6 +621,9 @@ class Jinja2YamlLoader(Jinja2Loader): yaml_str = super(Jinja2YamlLoader, self).format(**kwargs) return LateYamlLoader(yaml_str, self) + def __deepcopy__(self, memo): + return Jinja2YamlLoader(self._contents, self._search_path) + class CustomLoaderCollection(object): """Helper class to format a collection of CustomLoader objects""" diff --git a/tests/yamlparser/fixtures/jinja-yaml04-deepcopy.xml b/tests/yamlparser/fixtures/jinja-yaml04-deepcopy.xml new file mode 100644 index 000000000..2cbd4fafd --- /dev/null +++ b/tests/yamlparser/fixtures/jinja-yaml04-deepcopy.xml @@ -0,0 +1,38 @@ + + + + <!-- Managed by Jenkins Job Builder --> + false + false + false + false + true + + + + + echo "['repo-1', 'repo-2', 'repo-a1', 'repo-a2']" + + + + + + + + + <!-- Managed by Jenkins Job Builder --> + false + false + false + false + true + + + + + echo "['repo-1', 'repo-2', 'repo-b1', 'repo-b2']" + + + + + diff --git a/tests/yamlparser/fixtures/jinja-yaml04-deepcopy.yaml b/tests/yamlparser/fixtures/jinja-yaml04-deepcopy.yaml new file mode 100644 index 000000000..17a91a31e --- /dev/null +++ b/tests/yamlparser/fixtures/jinja-yaml04-deepcopy.yaml @@ -0,0 +1,28 @@ +- job-template: + name: 'test-job-template-{variant}' + builders: + - shell: + echo "{repos}" + +- project: + name: test-project + repos_common: + - repo-1 + - repo-2 + jobs: + - 'test-job-template-{variant}': + variant: 'a' + repos: !j2-yaml: | + {% for repo in repos_common %} + - {{ repo }} + {% endfor %} + - repo-a1 + - repo-a2 + - 'test-job-template-{variant}': + variant: 'b' + repos: !j2-yaml: | + {% for repo in repos_common %} + - {{ repo }} + {% endfor %} + - repo-b1 + - repo-b2