From 4fe960653068895c7bbfab1ccf3a9c38ecbac1e5 Mon Sep 17 00:00:00 2001 From: Matt Clay Date: Thu, 8 May 2025 15:45:53 -0700 Subject: [PATCH] template module - render `None` as empty string (#85121) * template module - render `None` as empty string * Update changelogs/fragments/template-none.yml Co-authored-by: Matt Davis <6775756+nitzmahone@users.noreply.github.com> --------- Co-authored-by: Matt Davis <6775756+nitzmahone@users.noreply.github.com> --- changelogs/fragments/template-none.yml | 2 ++ lib/ansible/plugins/action/template.py | 3 +++ test/integration/targets/lookup_template/tasks/main.yml | 4 ++++ .../targets/lookup_template/templates/none.j2 | 1 + test/integration/targets/template/tasks/main.yml | 9 +++++++++ test/integration/targets/template/templates/none.j2 | 1 + 6 files changed, 20 insertions(+) create mode 100644 changelogs/fragments/template-none.yml create mode 100644 test/integration/targets/lookup_template/templates/none.j2 create mode 100644 test/integration/targets/template/templates/none.j2 diff --git a/changelogs/fragments/template-none.yml b/changelogs/fragments/template-none.yml new file mode 100644 index 00000000000..bbe61d6ec73 --- /dev/null +++ b/changelogs/fragments/template-none.yml @@ -0,0 +1,2 @@ +bugfixes: + - template action - Template files where the entire file's output renders as ``None`` are no longer emitted as the string "None", but instead render to an empty file as in previous releases. diff --git a/lib/ansible/plugins/action/template.py b/lib/ansible/plugins/action/template.py index 8a306d235c4..2f339229b54 100644 --- a/lib/ansible/plugins/action/template.py +++ b/lib/ansible/plugins/action/template.py @@ -132,6 +132,9 @@ class ActionModule(ActionBase): data_templar = self._templar.copy_with_new_env(searchpath=searchpath, available_variables=temp_vars) resultant = data_templar.template(template_data, escape_backslashes=False, overrides=overrides) + if resultant is None: + resultant = '' + new_task = self._task.copy() # mode is either the mode from task.args or the mode of the source file if the task.args # mode == 'preserve' diff --git a/test/integration/targets/lookup_template/tasks/main.yml b/test/integration/targets/lookup_template/tasks/main.yml index a248c1068f5..48838f64079 100644 --- a/test/integration/targets/lookup_template/tasks/main.yml +++ b/test/integration/targets/lookup_template/tasks/main.yml @@ -32,3 +32,7 @@ - lookup('template', 'dict.j2') is not mapping - include_tasks: trim_blocks.yml + +- name: Verify templates with no rendered content return `None` + assert: + that: "{{ lookup('template', 'none.j2') is none }}" diff --git a/test/integration/targets/lookup_template/templates/none.j2 b/test/integration/targets/lookup_template/templates/none.j2 new file mode 100644 index 00000000000..b5c3460d5f3 --- /dev/null +++ b/test/integration/targets/lookup_template/templates/none.j2 @@ -0,0 +1 @@ +{# a template with no content will render as `None` #} diff --git a/test/integration/targets/template/tasks/main.yml b/test/integration/targets/template/tasks/main.yml index 83ddca3b0c3..d0c59569e57 100644 --- a/test/integration/targets/template/tasks/main.yml +++ b/test/integration/targets/template/tasks/main.yml @@ -19,6 +19,15 @@ - set_fact: output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}" +- name: render a template which has no content + template: + src: none.j2 + dest: '{{ output_dir }}/none.templated' + +- name: verify a template with no content renders as an empty string + assert: + that: "{{ lookup('file', output_dir ~ '/none.templated') == '' }}" + - name: get default group shell: id -gn register: group diff --git a/test/integration/targets/template/templates/none.j2 b/test/integration/targets/template/templates/none.j2 new file mode 100644 index 00000000000..b5c3460d5f3 --- /dev/null +++ b/test/integration/targets/template/templates/none.j2 @@ -0,0 +1 @@ +{# a template with no content will render as `None` #}