From 1b98ef17225aeccc2927a31b397434457aeca287 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Mon, 4 Nov 2024 10:36:13 -0800 Subject: [PATCH] lookup_template: added trim_blocks option * Allow user to control the trimming of blocks while templating * Added tests * Updated documentation and example Fixes: #75962 Signed-off-by: Abhijeet Kasurde --- changelogs/fragments/trim_blocks.yml | 3 ++ lib/ansible/plugins/lookup/template.py | 26 +++++++++++---- .../files/trim_blocks_false.expected | 4 +++ .../files/trim_blocks_true.expected | 2 ++ .../targets/lookup_template/tasks/main.yml | 2 ++ .../lookup_template/tasks/trim_blocks.yml | 32 +++++++++++++++++++ .../lookup_template/templates/trim_blocks.j2 | 4 +++ 7 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 changelogs/fragments/trim_blocks.yml create mode 100644 test/integration/targets/lookup_template/files/trim_blocks_false.expected create mode 100644 test/integration/targets/lookup_template/files/trim_blocks_true.expected create mode 100644 test/integration/targets/lookup_template/tasks/trim_blocks.yml create mode 100644 test/integration/targets/lookup_template/templates/trim_blocks.j2 diff --git a/changelogs/fragments/trim_blocks.yml b/changelogs/fragments/trim_blocks.yml new file mode 100644 index 00000000000..80eba8a1a7c --- /dev/null +++ b/changelogs/fragments/trim_blocks.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - lookup_template - add an option to trim blocks while templating (https://github.com/ansible/ansible/issues/75962). diff --git a/lib/ansible/plugins/lookup/template.py b/lib/ansible/plugins/lookup/template.py index b2508d01b6c..6f1f47e446e 100644 --- a/lib/ansible/plugins/lookup/template.py +++ b/lib/ansible/plugins/lookup/template.py @@ -17,8 +17,8 @@ DOCUMENTATION = """ convert_data: type: bool description: - - Whether to convert YAML into data. If False, strings that are YAML will be left untouched. - - Mutually exclusive with the jinja2_native option. + - Whether to convert YAML into data. If V(False), strings that are YAML will be left untouched. + - Mutually exclusive with the O(jinja2_native) option. default: true variable_start_string: description: The string marking the beginning of a print statement. @@ -33,10 +33,10 @@ DOCUMENTATION = """ jinja2_native: description: - Controls whether to use Jinja2 native types. - - It is off by default even if global jinja2_native is True. - - Has no effect if global jinja2_native is False. + - It is off by default even if global O(jinja2_native) is V(True). + - Has no effect if global O(jinja2_native) is V(False). - This offers more flexibility than the template module which does not use Jinja2 native types at all. - - Mutually exclusive with the convert_data option. + - Mutually exclusive with the O(convert_data) option. default: False version_added: '2.11' type: bool @@ -55,6 +55,13 @@ DOCUMENTATION = """ version_added: '2.12' type: str default: '#}' + trim_blocks: + description: + - Determine when newlines should be removed from blocks. + - When set to V(yes) the first newline after a block is removed (block, not variable tag!). + type: bool + default: yes + version_added: '2.19' seealso: - ref: playbook_task_paths description: Search paths used for relative templates. @@ -72,6 +79,11 @@ EXAMPLES = """ - name: show templating results with different comment start and end string ansible.builtin.debug: msg: "{{ lookup('ansible.builtin.template', './some_template.j2', comment_start_string='[#', comment_end_string='#]') }}" + +- name: show templating results with trim_blocks + ansible.builtin.debug: + msg: "{{ lookup('ansible.builtin.template', './some_template.j2', trim_blocks=True) }}" + """ RETURN = """ @@ -113,6 +125,7 @@ class LookupModule(LookupBase): variable_end_string = self.get_option('variable_end_string') comment_start_string = self.get_option('comment_start_string') comment_end_string = self.get_option('comment_end_string') + trim_blocks = self.get_option('trim_blocks') if jinja2_native: templar = self._templar @@ -154,7 +167,8 @@ class LookupModule(LookupBase): variable_start_string=variable_start_string, variable_end_string=variable_end_string, comment_start_string=comment_start_string, - comment_end_string=comment_end_string + comment_end_string=comment_end_string, + trim_blocks=trim_blocks, ) res = templar.template(template_data, preserve_trailing_newlines=True, convert_data=convert_data_p, escape_backslashes=False, diff --git a/test/integration/targets/lookup_template/files/trim_blocks_false.expected b/test/integration/targets/lookup_template/files/trim_blocks_false.expected new file mode 100644 index 00000000000..283cefc8df3 --- /dev/null +++ b/test/integration/targets/lookup_template/files/trim_blocks_false.expected @@ -0,0 +1,4 @@ + +Hello world + +Goodbye diff --git a/test/integration/targets/lookup_template/files/trim_blocks_true.expected b/test/integration/targets/lookup_template/files/trim_blocks_true.expected new file mode 100644 index 00000000000..03acd5d37a3 --- /dev/null +++ b/test/integration/targets/lookup_template/files/trim_blocks_true.expected @@ -0,0 +1,2 @@ +Hello world +Goodbye diff --git a/test/integration/targets/lookup_template/tasks/main.yml b/test/integration/targets/lookup_template/tasks/main.yml index 9ebdf0c5ac9..8c6a9b29c60 100644 --- a/test/integration/targets/lookup_template/tasks/main.yml +++ b/test/integration/targets/lookup_template/tasks/main.yml @@ -32,3 +32,5 @@ - lookup('template', 'dict.j2') is mapping - lookup('template', 'dict.j2', convert_data=True) is mapping - lookup('template', 'dict.j2', convert_data=False) is not mapping + +- include_tasks: trim_blocks.yml diff --git a/test/integration/targets/lookup_template/tasks/trim_blocks.yml b/test/integration/targets/lookup_template/tasks/trim_blocks.yml new file mode 100644 index 00000000000..b82fc0067b8 --- /dev/null +++ b/test/integration/targets/lookup_template/tasks/trim_blocks.yml @@ -0,0 +1,32 @@ +# VERIFY trim_blocks +- name: Render a template with "trim_blocks" set to False + copy: + content: "{{ lookup('template', 'trim_blocks.j2', trim_blocks=False) }}" + dest: "{{ output_dir }}/trim_blocks_false.templated" + register: trim_blocks_false_result + +- name: Get checksum of known good trim_blocks_false.expected + stat: + path: "{{ role_path }}/files/trim_blocks_false.expected" + register: trim_blocks_false_good + +- name: Verify templated trim_blocks_false matches known good using checksum + assert: + that: + - "trim_blocks_false_result.checksum == trim_blocks_false_good.stat.checksum" + +- name: Render a template with "trim_blocks" set to True + copy: + content: "{{ lookup('template', 'trim_blocks.j2', trim_blocks=True) }}" + dest: "{{ output_dir }}/trim_blocks_true.templated" + register: trim_blocks_true_result + +- name: Get checksum of known good trim_blocks_true.expected + stat: + path: "{{ role_path }}/files/trim_blocks_true.expected" + register: trim_blocks_true_good + +- name: Verify templated trim_blocks_true matches known good using checksum + assert: + that: + - "trim_blocks_true_result.checksum == trim_blocks_true_good.stat.checksum" diff --git a/test/integration/targets/lookup_template/templates/trim_blocks.j2 b/test/integration/targets/lookup_template/templates/trim_blocks.j2 new file mode 100644 index 00000000000..824a0a03458 --- /dev/null +++ b/test/integration/targets/lookup_template/templates/trim_blocks.j2 @@ -0,0 +1,4 @@ +{% if True %} +Hello world +{% endif %} +Goodbye