diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 16:04:21 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 16:04:21 +0000 |
commit | 8a754e0858d922e955e71b253c139e071ecec432 (patch) | |
tree | 527d16e74bfd1840c85efd675fdecad056c54107 /test/integration/targets/template | |
parent | Initial commit. (diff) | |
download | ansible-core-upstream/2.14.3.tar.xz ansible-core-upstream/2.14.3.zip |
Adding upstream version 2.14.3.upstream/2.14.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
88 files changed, 1460 insertions, 0 deletions
diff --git a/test/integration/targets/template/6653.yml b/test/integration/targets/template/6653.yml new file mode 100644 index 0000000..970478f --- /dev/null +++ b/test/integration/targets/template/6653.yml @@ -0,0 +1,10 @@ +- hosts: localhost + gather_facts: no + vars: + mylist: + - alpha + - bravo + tasks: + - name: Should not fail on undefined variable + set_fact: + template_result: "{{ lookup('template', '6653.j2') }}" diff --git a/test/integration/targets/template/72262.yml b/test/integration/targets/template/72262.yml new file mode 100644 index 0000000..33c610d --- /dev/null +++ b/test/integration/targets/template/72262.yml @@ -0,0 +1,6 @@ +- hosts: localhost + gather_facts: no + tasks: + - name: Should not fail on undefined variable + set_fact: + template_result: "{{ lookup('template', '72262.j2') }}" diff --git a/test/integration/targets/template/72615.yml b/test/integration/targets/template/72615.yml new file mode 100644 index 0000000..153cfd6 --- /dev/null +++ b/test/integration/targets/template/72615.yml @@ -0,0 +1,18 @@ +- hosts: localhost + gather_facts: no + vars: + foo: "top-level-foo" + tasks: + - set_fact: + template_result: "{{ lookup('template', '72615.j2') }}" + + - assert: + that: + - "'template-level-bar' in template_result" + - "'template-nested-level-bar' in template_result" + + - assert: + that: + - "'top-level-foo' not in template_result" + - "'template-level-foo' in template_result" + - "'template-nested-level-foo' in template_result" diff --git a/test/integration/targets/template/aliases b/test/integration/targets/template/aliases new file mode 100644 index 0000000..4e09af1 --- /dev/null +++ b/test/integration/targets/template/aliases @@ -0,0 +1,3 @@ +needs/root +shippable/posix/group4 +context/controller # this "module" is actually an action that runs on the controller diff --git a/test/integration/targets/template/ansible_managed.cfg b/test/integration/targets/template/ansible_managed.cfg new file mode 100644 index 0000000..3626429 --- /dev/null +++ b/test/integration/targets/template/ansible_managed.cfg @@ -0,0 +1,2 @@ +[defaults] +ansible_managed=ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host} diff --git a/test/integration/targets/template/ansible_managed.yml b/test/integration/targets/template/ansible_managed.yml new file mode 100644 index 0000000..2bd7c2c --- /dev/null +++ b/test/integration/targets/template/ansible_managed.yml @@ -0,0 +1,14 @@ +--- +- hosts: testhost + gather_facts: False + tasks: + - set_fact: + output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}" + - file: + path: '{{ output_dir }}/café.txt' + state: 'absent' + # Smoketest that ansible_managed with non-ascii chars works: + # https://github.com/ansible/ansible/issues/27262 + - template: + src: 'templates/café.j2' + dest: '{{ output_dir }}/café.txt' diff --git a/test/integration/targets/template/badnull1.cfg b/test/integration/targets/template/badnull1.cfg new file mode 100644 index 0000000..e1d0688 --- /dev/null +++ b/test/integration/targets/template/badnull1.cfg @@ -0,0 +1,2 @@ +[defaults] +null_representation = null diff --git a/test/integration/targets/template/badnull2.cfg b/test/integration/targets/template/badnull2.cfg new file mode 100644 index 0000000..058ca48 --- /dev/null +++ b/test/integration/targets/template/badnull2.cfg @@ -0,0 +1,2 @@ +[defaults] +null_representation = '' diff --git a/test/integration/targets/template/badnull3.cfg b/test/integration/targets/template/badnull3.cfg new file mode 100644 index 0000000..3c743fb --- /dev/null +++ b/test/integration/targets/template/badnull3.cfg @@ -0,0 +1,2 @@ +[defaults] +null_representation = none diff --git a/test/integration/targets/template/corner_cases.yml b/test/integration/targets/template/corner_cases.yml new file mode 100644 index 0000000..9d41ed9 --- /dev/null +++ b/test/integration/targets/template/corner_cases.yml @@ -0,0 +1,55 @@ +- name: test tempating corner cases + hosts: localhost + gather_facts: false + vars: + empty_list: [] + dont: I SHOULD NOT BE TEMPLATED + other: I WORK + tasks: + - name: 'ensure we are not interpolating data from outside of j2 delmiters' + assert: + that: + - '"I SHOULD NOT BE TEMPLATED" not in adjacent' + - globals1 == "[[], globals()]" + - globals2 == "[[], globals]" + - left_hand == '[1] + [2]' + - left_hand_2 == '[1 + 2 * 3 / 4] + [-2.5, 2.5, 3.5]' + vars: + adjacent: "{{ empty_list }} + [dont]" + globals1: "[{{ empty_list }}, globals()]" + globals2: "[{{ empty_list }}, globals]" + left_hand: '[1] + {{ [2] }}' + left_hand_2: '[1 + 2 * 3 / 4] + {{ [-2.5, +2.5, 1 + 2.5] }}' + + - name: 'ensure we can add lists' + assert: + that: + - (empty_list + [other]) == [other] + - (empty_list + [other, other]) == [other, other] + - (dont_exist|default([]) + [other]) == [other] + - ([other] + [empty_list, other]) == [other, [], other] + + - name: 'ensure comments go away and we still dont interpolate in string' + assert: + that: + - 'comm1 == " + [dont]"' + - 'comm2 == " #} + [dont]"' + vars: + comm1: '{# {{nothing}} {# #} + [dont]' + comm2: "{# {{nothing}} {# #} #} + [dont]" + + - name: test additions with facts, set them up + set_fact: + inames: [] + iname: "{{ prefix ~ '-options' }}" + iname_1: "{{ prefix ~ '-options-1' }}" + vars: + prefix: 'bo' + + - name: add the facts + set_fact: + inames: '{{ inames + [iname, iname_1] }}' + + - assert: + that: + - inames == ['bo-options', 'bo-options-1'] diff --git a/test/integration/targets/template/custom_tasks/tasks/main.yml b/test/integration/targets/template/custom_tasks/tasks/main.yml new file mode 100644 index 0000000..182f7cc --- /dev/null +++ b/test/integration/targets/template/custom_tasks/tasks/main.yml @@ -0,0 +1,15 @@ +--- +- set_fact: + output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}" + +- template: + src: test + dest: "{{ output_dir }}/templated_test" + register: custom_template_result + +- debug: + msg: "{{ custom_template_result }}" + +- assert: + that: + - custom_template_result.changed diff --git a/test/integration/targets/template/custom_tasks/templates/test b/test/integration/targets/template/custom_tasks/templates/test new file mode 100644 index 0000000..d033f12 --- /dev/null +++ b/test/integration/targets/template/custom_tasks/templates/test @@ -0,0 +1 @@ +Sample Text diff --git a/test/integration/targets/template/custom_template.yml b/test/integration/targets/template/custom_template.yml new file mode 100644 index 0000000..e5c7aac --- /dev/null +++ b/test/integration/targets/template/custom_template.yml @@ -0,0 +1,4 @@ +- hosts: testhost + gather_facts: yes + roles: + - { role: custom_tasks } diff --git a/test/integration/targets/template/files/custom_comment_string.expected b/test/integration/targets/template/files/custom_comment_string.expected new file mode 100644 index 0000000..f3a08f7 --- /dev/null +++ b/test/integration/targets/template/files/custom_comment_string.expected @@ -0,0 +1,2 @@ +Before +After diff --git a/test/integration/targets/template/files/encoding_1252_utf-8.expected b/test/integration/targets/template/files/encoding_1252_utf-8.expected new file mode 100644 index 0000000..0d3cc35 --- /dev/null +++ b/test/integration/targets/template/files/encoding_1252_utf-8.expected @@ -0,0 +1 @@ +windows-1252 Special Characters: €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ diff --git a/test/integration/targets/template/files/encoding_1252_windows-1252.expected b/test/integration/targets/template/files/encoding_1252_windows-1252.expected new file mode 100644 index 0000000..7fb94a7 --- /dev/null +++ b/test/integration/targets/template/files/encoding_1252_windows-1252.expected @@ -0,0 +1 @@ +windows-1252 Special Characters: diff --git a/test/integration/targets/template/files/foo-py26.txt b/test/integration/targets/template/files/foo-py26.txt new file mode 100644 index 0000000..76b0bb5 --- /dev/null +++ b/test/integration/targets/template/files/foo-py26.txt @@ -0,0 +1,9 @@ +templated_var_loaded + +{ + "bool": true, + "multi_part": "1Foo", + "null_type": null, + "number": 5, + "string_num": "5" +} diff --git a/test/integration/targets/template/files/foo.dos.txt b/test/integration/targets/template/files/foo.dos.txt new file mode 100644 index 0000000..b716eca --- /dev/null +++ b/test/integration/targets/template/files/foo.dos.txt @@ -0,0 +1,3 @@ +BEGIN
+templated_var_loaded
+END
diff --git a/test/integration/targets/template/files/foo.txt b/test/integration/targets/template/files/foo.txt new file mode 100644 index 0000000..58af3be --- /dev/null +++ b/test/integration/targets/template/files/foo.txt @@ -0,0 +1,9 @@ +templated_var_loaded + +{ + "bool": true, + "multi_part": "1Foo", + "null_type": null, + "number": 5, + "string_num": "5" +} diff --git a/test/integration/targets/template/files/foo.unix.txt b/test/integration/targets/template/files/foo.unix.txt new file mode 100644 index 0000000..d33849f --- /dev/null +++ b/test/integration/targets/template/files/foo.unix.txt @@ -0,0 +1,3 @@ +BEGIN +templated_var_loaded +END diff --git a/test/integration/targets/template/files/import_as.expected b/test/integration/targets/template/files/import_as.expected new file mode 100644 index 0000000..fc6ea02 --- /dev/null +++ b/test/integration/targets/template/files/import_as.expected @@ -0,0 +1,3 @@ +hello world import as +WIBBLE +Goodbye diff --git a/test/integration/targets/template/files/import_as_with_context.expected b/test/integration/targets/template/files/import_as_with_context.expected new file mode 100644 index 0000000..7099a47 --- /dev/null +++ b/test/integration/targets/template/files/import_as_with_context.expected @@ -0,0 +1,2 @@ +hello world as qux with context +WIBBLE diff --git a/test/integration/targets/template/files/import_with_context.expected b/test/integration/targets/template/files/import_with_context.expected new file mode 100644 index 0000000..5323655 --- /dev/null +++ b/test/integration/targets/template/files/import_with_context.expected @@ -0,0 +1,3 @@ +hello world with context +WIBBLE +Goodbye diff --git a/test/integration/targets/template/files/lstrip_blocks_false.expected b/test/integration/targets/template/files/lstrip_blocks_false.expected new file mode 100644 index 0000000..1260001 --- /dev/null +++ b/test/integration/targets/template/files/lstrip_blocks_false.expected @@ -0,0 +1,4 @@ + hello world + hello world + hello world + diff --git a/test/integration/targets/template/files/lstrip_blocks_true.expected b/test/integration/targets/template/files/lstrip_blocks_true.expected new file mode 100644 index 0000000..1b11f8b --- /dev/null +++ b/test/integration/targets/template/files/lstrip_blocks_true.expected @@ -0,0 +1,3 @@ +hello world +hello world +hello world diff --git a/test/integration/targets/template/files/override_colon_value.expected b/test/integration/targets/template/files/override_colon_value.expected new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/test/integration/targets/template/files/override_colon_value.expected @@ -0,0 +1 @@ +foo diff --git a/test/integration/targets/template/files/string_type_filters.expected b/test/integration/targets/template/files/string_type_filters.expected new file mode 100644 index 0000000..989c356 --- /dev/null +++ b/test/integration/targets/template/files/string_type_filters.expected @@ -0,0 +1,4 @@ +{ + "foo": "bar", + "foobar": 1 +} diff --git a/test/integration/targets/template/files/trim_blocks_false.expected b/test/integration/targets/template/files/trim_blocks_false.expected new file mode 100644 index 0000000..283cefc --- /dev/null +++ b/test/integration/targets/template/files/trim_blocks_false.expected @@ -0,0 +1,4 @@ + +Hello world + +Goodbye diff --git a/test/integration/targets/template/files/trim_blocks_true.expected b/test/integration/targets/template/files/trim_blocks_true.expected new file mode 100644 index 0000000..03acd5d --- /dev/null +++ b/test/integration/targets/template/files/trim_blocks_true.expected @@ -0,0 +1,2 @@ +Hello world +Goodbye diff --git a/test/integration/targets/template/filter_plugins.yml b/test/integration/targets/template/filter_plugins.yml new file mode 100644 index 0000000..c3e97a5 --- /dev/null +++ b/test/integration/targets/template/filter_plugins.yml @@ -0,0 +1,9 @@ +- hosts: localhost + gather_facts: no + tasks: + - debug: + msg: "force templating in delegate_to before we hit the second one with a filter" + delegate_to: "{{ 'localhost' }}" + + - include_role: + name: role_filter diff --git a/test/integration/targets/template/in_template_overrides.j2 b/test/integration/targets/template/in_template_overrides.j2 new file mode 100644 index 0000000..2247607 --- /dev/null +++ b/test/integration/targets/template/in_template_overrides.j2 @@ -0,0 +1,5 @@ +#jinja2:variable_start_string:'<<' , variable_end_string:'>>' +var_a: << var_a >> +var_b: << var_b >> +var_c: << var_c >> +var_d: << var_d >> diff --git a/test/integration/targets/template/in_template_overrides.yml b/test/integration/targets/template/in_template_overrides.yml new file mode 100644 index 0000000..3c2d4d9 --- /dev/null +++ b/test/integration/targets/template/in_template_overrides.yml @@ -0,0 +1,28 @@ +- hosts: localhost + gather_facts: false + vars: + var_a: "value" + var_b: "{{ var_a }}" + var_c: "<< var_a >>" + tasks: + - set_fact: + var_d: "{{ var_a }}" + + - block: + - template: + src: in_template_overrides.j2 + dest: out.txt + + - command: cat out.txt + register: out + + - assert: + that: + - "'var_a: value' in out.stdout" + - "'var_b: value' in out.stdout" + - "'var_c: << var_a >>' in out.stdout" + - "'var_d: value' in out.stdout" + always: + - file: + path: out.txt + state: absent diff --git a/test/integration/targets/template/lazy_eval.yml b/test/integration/targets/template/lazy_eval.yml new file mode 100644 index 0000000..856b710 --- /dev/null +++ b/test/integration/targets/template/lazy_eval.yml @@ -0,0 +1,24 @@ +- hosts: testhost + gather_facts: false + vars: + deep_undefined: "{{ nested_undefined_variable }}" + tasks: + - name: These do not throw an error, deep_undefined is just evaluated to undefined, since 2.14 + assert: + that: + - lazy_eval or deep_undefined + - deep_undefined is undefined + - deep_undefined|default('defaulted') == 'defaulted' + vars: + lazy_eval: true + + - name: EXPECTED FAILURE actually using deep_undefined fails + debug: + msg: "{{ deep_undefined }}" + ignore_errors: true + register: res + + - assert: + that: + - res.failed + - res.msg is contains("'nested_undefined_variable' is undefined") diff --git a/test/integration/targets/template/meta/main.yml b/test/integration/targets/template/meta/main.yml new file mode 100644 index 0000000..06d4fd2 --- /dev/null +++ b/test/integration/targets/template/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_tests + - setup_nobody diff --git a/test/integration/targets/template/role_filter/filter_plugins/myplugin.py b/test/integration/targets/template/role_filter/filter_plugins/myplugin.py new file mode 100644 index 0000000..b0a8889 --- /dev/null +++ b/test/integration/targets/template/role_filter/filter_plugins/myplugin.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class FilterModule(object): + def filters(self): + return {'parse_ip': self.parse_ip} + + def parse_ip(self, ip): + return ip diff --git a/test/integration/targets/template/role_filter/tasks/main.yml b/test/integration/targets/template/role_filter/tasks/main.yml new file mode 100644 index 0000000..7d962a2 --- /dev/null +++ b/test/integration/targets/template/role_filter/tasks/main.yml @@ -0,0 +1,3 @@ +- name: test + command: echo hello + delegate_to: "{{ '127.0.0.1' | parse_ip }}" diff --git a/test/integration/targets/template/runme.sh b/test/integration/targets/template/runme.sh new file mode 100755 index 0000000..30163af --- /dev/null +++ b/test/integration/targets/template/runme.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +set -eux + +ANSIBLE_ROLES_PATH=../ ansible-playbook template.yml -i ../../inventory -v "$@" + +# Test for https://github.com/ansible/ansible/pull/35571 +ansible testhost -i testhost, -m debug -a 'msg={{ hostvars["localhost"] }}' -e "vars1={{ undef() }}" -e "vars2={{ vars1 }}" + +# Test for https://github.com/ansible/ansible/issues/27262 +ansible-playbook ansible_managed.yml -c ansible_managed.cfg -i ../../inventory -v "$@" + +# Test for #42585 +ANSIBLE_ROLES_PATH=../ ansible-playbook custom_template.yml -i ../../inventory -v "$@" + + +# Test for several corner cases #57188 +ansible-playbook corner_cases.yml -v "$@" + +# Test for #57351 +ansible-playbook filter_plugins.yml -v "$@" + +# https://github.com/ansible/ansible/issues/68699 +ansible-playbook unused_vars_include.yml -v "$@" + +# https://github.com/ansible/ansible/issues/55152 +ansible-playbook undefined_var_info.yml -v "$@" + +# https://github.com/ansible/ansible/issues/72615 +ansible-playbook 72615.yml -v "$@" + +# https://github.com/ansible/ansible/issues/6653 +ansible-playbook 6653.yml -v "$@" + +# https://github.com/ansible/ansible/issues/72262 +ansible-playbook 72262.yml -v "$@" + +# ensure unsafe is preserved, even with extra newlines +ansible-playbook unsafe.yml -v "$@" + +# ensure Jinja2 overrides from a template are used +ansible-playbook in_template_overrides.yml -v "$@" + +ansible-playbook lazy_eval.yml -i ../../inventory -v "$@" + +ansible-playbook undefined_in_import.yml -i ../../inventory -v "$@" + +# ensure diff null configs work #76493 +for badcfg in "badnull1" "badnull2" "badnull3" +do + [ -f "./${badcfg}.cfg" ] + ANSIBLE_CONFIG="./${badcfg}.cfg" ansible-config dump --only-changed +done + diff --git a/test/integration/targets/template/tasks/backup_test.yml b/test/integration/targets/template/tasks/backup_test.yml new file mode 100644 index 0000000..eb4eff1 --- /dev/null +++ b/test/integration/targets/template/tasks/backup_test.yml @@ -0,0 +1,60 @@ +# https://github.com/ansible/ansible/issues/24408 + +- set_fact: + t_username: templateuser1 + t_groupname: templateuser1 + +- name: create the test group + group: + name: "{{ t_groupname }}" + +- name: create the test user + user: + name: "{{ t_username }}" + group: "{{ t_groupname }}" + createhome: no + +- name: set the dest file + set_fact: + t_dest: "{{ output_dir + '/tfile_dest.txt' }}" + +- name: create the old file + file: + path: "{{ t_dest }}" + state: touch + mode: 0777 + owner: "{{ t_username }}" + group: "{{ t_groupname }}" + +- name: failsafe attr change incase underlying system does not support it + shell: chattr =j "{{ t_dest }}" + ignore_errors: True + +- name: run the template + template: + src: foo.j2 + dest: "{{ t_dest }}" + backup: True + register: t_backup_res + +- name: check the data for the backup + stat: + path: "{{ t_backup_res.backup_file }}" + register: t_backup_stats + +- name: validate result of preserved backup + assert: + that: + - 't_backup_stats.stat.mode == "0777"' + - 't_backup_stats.stat.pw_name == t_username' + - 't_backup_stats.stat.gr_name == t_groupname' + +- name: cleanup the user + user: + name: "{{ t_username }}" + state: absent + +- name: cleanup the group + user: + name: "{{ t_groupname }}" + state: absent diff --git a/test/integration/targets/template/tasks/main.yml b/test/integration/targets/template/tasks/main.yml new file mode 100644 index 0000000..c0d2e11 --- /dev/null +++ b/test/integration/targets/template/tasks/main.yml @@ -0,0 +1,811 @@ +# test code for the template module +# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com> + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +- set_fact: + output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}" + +- name: show python interpreter + debug: + msg: "{{ ansible_python['executable'] }}" + +- name: show jinja2 version + debug: + msg: "{{ lookup('pipe', '{{ ansible_python[\"executable\"] }} -c \"import jinja2; print(jinja2.__version__)\"') }}" + +- name: get default group + shell: id -gn + register: group + +- name: fill in a basic template + template: src=foo.j2 dest={{output_dir}}/foo.templated mode=0644 + register: template_result + +- assert: + that: + - "'changed' in template_result" + - "'dest' in template_result" + - "'group' in template_result" + - "'gid' in template_result" + - "'md5sum' in template_result" + - "'checksum' in template_result" + - "'owner' in template_result" + - "'size' in template_result" + - "'src' in template_result" + - "'state' in template_result" + - "'uid' in template_result" + +- name: verify that the file was marked as changed + assert: + that: + - "template_result.changed == true" + +# Basic template with non-ascii names +- name: Check that non-ascii source and dest work + template: + src: 'café.j2' + dest: '{{ output_dir }}/café.txt' + register: template_results + +- name: Check that the resulting file exists + stat: + path: '{{ output_dir }}/café.txt' + register: stat_results + +- name: Check that template created the right file + assert: + that: + - 'template_results is changed' + - 'stat_results.stat["exists"]' + +# test for import with context on jinja-2.9 See https://github.com/ansible/ansible/issues/20494 +- name: fill in a template using import with context ala issue 20494 + template: src=import_with_context.j2 dest={{output_dir}}/import_with_context.templated mode=0644 + register: template_result + +- name: copy known good import_with_context.expected into place + copy: src=import_with_context.expected dest={{output_dir}}/import_with_context.expected + +- name: compare templated file to known good import_with_context + shell: diff -uw {{output_dir}}/import_with_context.templated {{output_dir}}/import_with_context.expected + register: diff_result + +- name: verify templated import_with_context matches known good + assert: + that: + - 'diff_result.stdout == ""' + - "diff_result.rc == 0" + +# test for nested include https://github.com/ansible/ansible/issues/34886 +- name: test if parent variables are defined in nested include + template: src=for_loop.j2 dest={{output_dir}}/for_loop.templated mode=0644 + +- name: save templated output + shell: "cat {{output_dir}}/for_loop.templated" + register: for_loop_out +- debug: var=for_loop_out +- name: verify variables got templated + assert: + that: + - '"foo" in for_loop_out.stdout' + - '"bar" in for_loop_out.stdout' + - '"bam" in for_loop_out.stdout' + +# test for 'import as' on jinja-2.9 See https://github.com/ansible/ansible/issues/20494 +- name: fill in a template using import as ala fails2 case in issue 20494 + template: src=import_as.j2 dest={{output_dir}}/import_as.templated mode=0644 + register: import_as_template_result + +- name: copy known good import_as.expected into place + copy: src=import_as.expected dest={{output_dir}}/import_as.expected + +- name: compare templated file to known good import_as + shell: diff -uw {{output_dir}}/import_as.templated {{output_dir}}/import_as.expected + register: import_as_diff_result + +- name: verify templated import_as matches known good + assert: + that: + - 'import_as_diff_result.stdout == ""' + - "import_as_diff_result.rc == 0" + +# test for 'import as with context' on jinja-2.9 See https://github.com/ansible/ansible/issues/20494 +- name: fill in a template using import as with context ala fails2 case in issue 20494 + template: src=import_as_with_context.j2 dest={{output_dir}}/import_as_with_context.templated mode=0644 + register: import_as_with_context_template_result + +- name: copy known good import_as_with_context.expected into place + copy: src=import_as_with_context.expected dest={{output_dir}}/import_as_with_context.expected + +- name: compare templated file to known good import_as_with_context + shell: diff -uw {{output_dir}}/import_as_with_context.templated {{output_dir}}/import_as_with_context.expected + register: import_as_with_context_diff_result + +- name: verify templated import_as_with_context matches known good + assert: + that: + - 'import_as_with_context_diff_result.stdout == ""' + - "import_as_with_context_diff_result.rc == 0" + +# VERIFY comment_start_string and comment_end_string + +- name: Render a template with "comment_start_string" set to [# + template: + src: custom_comment_string.j2 + dest: "{{output_dir}}/custom_comment_string.templated" + comment_start_string: "[#" + comment_end_string: "#]" + register: custom_comment_string_result + +- name: Get checksum of known good custom_comment_string.expected + stat: + path: "{{role_path}}/files/custom_comment_string.expected" + register: custom_comment_string_good + +- name: Verify templated custom_comment_string matches known good using checksum + assert: + that: + - "custom_comment_string_result.checksum == custom_comment_string_good.stat.checksum" + +# VERIFY trim_blocks + +- name: Render a template with "trim_blocks" set to False + template: + src: trim_blocks.j2 + dest: "{{output_dir}}/trim_blocks_false.templated" + trim_blocks: False + 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 + template: + src: trim_blocks.j2 + dest: "{{output_dir}}/trim_blocks_true.templated" + trim_blocks: True + 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" + +# VERIFY lstrip_blocks + +- name: Render a template with "lstrip_blocks" set to False + template: + src: lstrip_blocks.j2 + dest: "{{output_dir}}/lstrip_blocks_false.templated" + lstrip_blocks: False + register: lstrip_blocks_false_result + +- name: Get checksum of known good lstrip_blocks_false.expected + stat: + path: "{{role_path}}/files/lstrip_blocks_false.expected" + register: lstrip_blocks_false_good + +- name: Verify templated lstrip_blocks_false matches known good using checksum + assert: + that: + - "lstrip_blocks_false_result.checksum == lstrip_blocks_false_good.stat.checksum" + +- name: Render a template with "lstrip_blocks" set to True + template: + src: lstrip_blocks.j2 + dest: "{{output_dir}}/lstrip_blocks_true.templated" + lstrip_blocks: True + register: lstrip_blocks_true_result + ignore_errors: True + +- name: Get checksum of known good lstrip_blocks_true.expected + stat: + path: "{{role_path}}/files/lstrip_blocks_true.expected" + register: lstrip_blocks_true_good + +- name: Verify templated lstrip_blocks_true matches known good using checksum + assert: + that: + - "lstrip_blocks_true_result.checksum == lstrip_blocks_true_good.stat.checksum" + +# VERIFY CONTENTS + +- name: copy known good into place + copy: src=foo.txt dest={{output_dir}}/foo.txt + +- name: compare templated file to known good + shell: diff -uw {{output_dir}}/foo.templated {{output_dir}}/foo.txt + register: diff_result + +- name: verify templated file matches known good + assert: + that: + - 'diff_result.stdout == ""' + - "diff_result.rc == 0" + +# VERIFY MODE + +- name: set file mode + file: path={{output_dir}}/foo.templated mode=0644 + register: file_result + +- name: ensure file mode did not change + assert: + that: + - "file_result.changed != True" + +# VERIFY dest as a directory does not break file attributes +# Note: expanduser is needed to go down the particular codepath that was broken before +- name: setup directory for test + file: state=directory dest={{output_dir | expanduser}}/template-dir mode=0755 owner=nobody group={{ group.stdout }} + +- name: set file mode when the destination is a directory + template: src=foo.j2 dest={{output_dir | expanduser}}/template-dir/ mode=0600 owner=root group={{ group.stdout }} + +- name: set file mode when the destination is a directory + template: src=foo.j2 dest={{output_dir | expanduser}}/template-dir/ mode=0600 owner=root group={{ group.stdout }} + register: file_result + +- name: check that the file has the correct attributes + stat: path={{output_dir | expanduser}}/template-dir/foo.j2 + register: file_attrs + +- assert: + that: + - "file_attrs.stat.uid == 0" + - "file_attrs.stat.pw_name == 'root'" + - "file_attrs.stat.mode == '0600'" + +- name: check that the containing directory did not change attributes + stat: path={{output_dir | expanduser}}/template-dir/ + register: dir_attrs + +- assert: + that: + - "dir_attrs.stat.uid != 0" + - "dir_attrs.stat.pw_name == 'nobody'" + - "dir_attrs.stat.mode == '0755'" + +- name: Check that template to a directory where the directory does not end with a / is allowed + template: src=foo.j2 dest={{output_dir | expanduser}}/template-dir mode=0600 owner=root group={{ group.stdout }} + +- name: make a symlink to the templated file + file: + path: '{{ output_dir }}/foo.symlink' + src: '{{ output_dir }}/foo.templated' + state: link + +- name: check that templating the symlink results in the file being templated + template: + src: foo.j2 + dest: '{{output_dir}}/foo.symlink' + mode: 0600 + follow: True + register: template_result + +- assert: + that: + - "template_result.changed == True" + +- name: check that the file has the correct attributes + stat: path={{output_dir | expanduser}}/template-dir/foo.j2 + register: file_attrs + +- assert: + that: + - "file_attrs.stat.mode == '0600'" + +- name: check that templating the symlink again makes no changes + template: + src: foo.j2 + dest: '{{output_dir}}/foo.symlink' + mode: 0600 + follow: True + register: template_result + +- assert: + that: + - "template_result.changed == False" + +# Test strange filenames + +- name: Create a temp dir for filename tests + file: + state: directory + dest: '{{ output_dir }}/filename-tests' + +- name: create a file with an unusual filename + template: + src: foo.j2 + dest: "{{ output_dir }}/filename-tests/foo t'e~m\\plated" + register: template_result + +- assert: + that: + - "template_result.changed == True" + +- name: check that the unusual filename was created + command: "ls {{ output_dir }}/filename-tests/" + register: unusual_results + +- assert: + that: + - "\"foo t'e~m\\plated\" in unusual_results.stdout_lines" + - "{{unusual_results.stdout_lines| length}} == 1" + +- name: check that the unusual filename can be checked for changes + template: + src: foo.j2 + dest: "{{ output_dir }}/filename-tests/foo t'e~m\\plated" + register: template_result + +- assert: + that: + - "template_result.changed == False" + + +# check_mode + +- name: fill in a basic template in check mode + template: src=short.j2 dest={{output_dir}}/short.templated + register: template_result + check_mode: True + +- name: check file exists + stat: path={{output_dir}}/short.templated + register: templated + +- name: verify that the file was marked as changed in check mode but was not created + assert: + that: + - "not templated.stat.exists" + - "template_result is changed" + +- name: fill in a basic template + template: src=short.j2 dest={{output_dir}}/short.templated + +- name: fill in a basic template in check mode + template: src=short.j2 dest={{output_dir}}/short.templated + register: template_result + check_mode: True + +- name: verify that the file was marked as not changes in check mode + assert: + that: + - "template_result is not changed" + - "'templated_var_loaded' in lookup('file', output_dir + '/short.templated')" + +- name: change var for the template + set_fact: + templated_var: "changed" + +- name: fill in a basic template with changed var in check mode + template: src=short.j2 dest={{output_dir}}/short.templated + register: template_result + check_mode: True + +- name: verify that the file was marked as changed in check mode but the content was not changed + assert: + that: + - "'templated_var_loaded' in lookup('file', output_dir + '/short.templated')" + - "template_result is changed" + +# Create a template using a child template, to ensure that variables +# are passed properly from the parent to subtemplate context (issue #20063) + +- name: test parent and subtemplate creation of context + template: src=parent.j2 dest={{output_dir}}/parent_and_subtemplate.templated + register: template_result + +- stat: path={{output_dir}}/parent_and_subtemplate.templated + +- name: verify that the parent and subtemplate creation worked + assert: + that: + - "template_result is changed" + +# +# template module can overwrite a file that's been hard linked +# https://github.com/ansible/ansible/issues/10834 +# + +- name: ensure test dir is absent + file: + path: '{{ output_dir | expanduser }}/hlink_dir' + state: absent + +- name: create test dir + file: + path: '{{ output_dir | expanduser }}/hlink_dir' + state: directory + +- name: template out test file to system 1 + template: + src: foo.j2 + dest: '{{ output_dir | expanduser }}/hlink_dir/test_file' + +- name: make hard link + file: + src: '{{ output_dir | expanduser }}/hlink_dir/test_file' + dest: '{{ output_dir | expanduser }}/hlink_dir/test_file_hlink' + state: hard + +- name: template out test file to system 2 + template: + src: foo.j2 + dest: '{{ output_dir | expanduser }}/hlink_dir/test_file' + register: hlink_result + +- name: check that the files are still hardlinked + stat: + path: '{{ output_dir | expanduser }}/hlink_dir/test_file' + register: orig_file + +- name: check that the files are still hardlinked + stat: + path: '{{ output_dir | expanduser }}/hlink_dir/test_file_hlink' + register: hlink_file + +# We've done nothing at this point to update the content of the file so it should still be hardlinked +- assert: + that: + - "hlink_result.changed == False" + - "orig_file.stat.inode == hlink_file.stat.inode" + +- name: change var for the template + set_fact: + templated_var: "templated_var_loaded" + +# UNIX TEMPLATE +- name: fill in a basic template (Unix) + template: + src: foo2.j2 + dest: '{{ output_dir }}/foo.unix.templated' + register: template_result + +- name: verify that the file was marked as changed (Unix) + assert: + that: + - 'template_result is changed' + +- name: fill in a basic template again (Unix) + template: + src: foo2.j2 + dest: '{{ output_dir }}/foo.unix.templated' + register: template_result2 + +- name: verify that the template was not changed (Unix) + assert: + that: + - 'template_result2 is not changed' + +# VERIFY UNIX CONTENTS +- name: copy known good into place (Unix) + copy: + src: foo.unix.txt + dest: '{{ output_dir }}/foo.unix.txt' + +- name: Dump templated file (Unix) + command: hexdump -C {{ output_dir }}/foo.unix.templated + +- name: Dump expected file (Unix) + command: hexdump -C {{ output_dir }}/foo.unix.txt + +- name: compare templated file to known good (Unix) + command: diff -u {{ output_dir }}/foo.unix.templated {{ output_dir }}/foo.unix.txt + register: diff_result + +- name: verify templated file matches known good (Unix) + assert: + that: + - 'diff_result.stdout == ""' + - "diff_result.rc == 0" + +# DOS TEMPLATE +- name: fill in a basic template (DOS) + template: + src: foo2.j2 + dest: '{{ output_dir }}/foo.dos.templated' + newline_sequence: '\r\n' + register: template_result + +- name: verify that the file was marked as changed (DOS) + assert: + that: + - 'template_result is changed' + +- name: fill in a basic template again (DOS) + template: + src: foo2.j2 + dest: '{{ output_dir }}/foo.dos.templated' + newline_sequence: '\r\n' + register: template_result2 + +- name: verify that the template was not changed (DOS) + assert: + that: + - 'template_result2 is not changed' + +# VERIFY DOS CONTENTS +- name: copy known good into place (DOS) + copy: + src: foo.dos.txt + dest: '{{ output_dir }}/foo.dos.txt' + +- name: Dump templated file (DOS) + command: hexdump -C {{ output_dir }}/foo.dos.templated + +- name: Dump expected file (DOS) + command: hexdump -C {{ output_dir }}/foo.dos.txt + +- name: compare templated file to known good (DOS) + command: diff -u {{ output_dir }}/foo.dos.templated {{ output_dir }}/foo.dos.txt + register: diff_result + +- name: verify templated file matches known good (DOS) + assert: + that: + - 'diff_result.stdout == ""' + - "diff_result.rc == 0" + +# VERIFY DOS CONTENTS +- name: copy known good into place (Unix) + copy: + src: foo.unix.txt + dest: '{{ output_dir }}/foo.unix.txt' + +- name: Dump templated file (Unix) + command: hexdump -C {{ output_dir }}/foo.unix.templated + +- name: Dump expected file (Unix) + command: hexdump -C {{ output_dir }}/foo.unix.txt + +- name: compare templated file to known good (Unix) + command: diff -u {{ output_dir }}/foo.unix.templated {{ output_dir }}/foo.unix.txt + register: diff_result + +- name: verify templated file matches known good (Unix) + assert: + that: + - 'diff_result.stdout == ""' + - "diff_result.rc == 0" + +# Check that mode=preserve works with template +- name: Create a template which has strange permissions + copy: + content: !unsafe '{{ ansible_managed }}\n' + dest: '{{ output_dir }}/foo-template.j2' + mode: 0547 + delegate_to: localhost + +- name: Use template with mode=preserve + template: + src: '{{ output_dir }}/foo-template.j2' + dest: '{{ output_dir }}/foo-templated.txt' + mode: 'preserve' + register: template_results + +- name: Get permissions from the templated file + stat: + path: '{{ output_dir }}/foo-templated.txt' + register: stat_results + +- name: Check that the resulting file has the correct permissions + assert: + that: + - 'template_results is changed' + - 'template_results.mode == "0547"' + - 'stat_results.stat["mode"] == "0547"' + +# Test output_encoding +- name: Prepare the list of encodings we want to check, including empty string for defaults + set_fact: + template_encoding_1252_encodings: ['', 'utf-8', 'windows-1252'] + +- name: Copy known good encoding_1252_*.expected into place + copy: + src: 'encoding_1252_{{ item | default("utf-8", true) }}.expected' + dest: '{{ output_dir }}/encoding_1252_{{ item }}.expected' + loop: '{{ template_encoding_1252_encodings }}' + +- name: Generate the encoding_1252_* files from templates using various encoding combinations + template: + src: 'encoding_1252.j2' + dest: '{{ output_dir }}/encoding_1252_{{ item }}.txt' + output_encoding: '{{ item }}' + loop: '{{ template_encoding_1252_encodings }}' + +- name: Compare the encoding_1252_* templated files to known good + command: diff -u {{ output_dir }}/encoding_1252_{{ item }}.expected {{ output_dir }}/encoding_1252_{{ item }}.txt + register: encoding_1252_diff_result + loop: '{{ template_encoding_1252_encodings }}' + +- name: Check that nested undefined values return Undefined + vars: + dict_var: + bar: {} + list_var: + - foo: {} + assert: + that: + - dict_var is defined + - dict_var.bar is defined + - dict_var.bar.baz is not defined + - dict_var.bar.baz | default('DEFAULT') == 'DEFAULT' + - dict_var.bar.baz.abc is not defined + - dict_var.bar.baz.abc | default('DEFAULT') == 'DEFAULT' + - dict_var.baz is not defined + - dict_var.baz.abc is not defined + - dict_var.baz.abc | default('DEFAULT') == 'DEFAULT' + - list_var.0 is defined + - list_var.1 is not defined + - list_var.0.foo is defined + - list_var.0.foo.bar is not defined + - list_var.0.foo.bar | default('DEFAULT') == 'DEFAULT' + - list_var.1.foo is not defined + - list_var.1.foo | default('DEFAULT') == 'DEFAULT' + - dict_var is defined + - dict_var['bar'] is defined + - dict_var['bar']['baz'] is not defined + - dict_var['bar']['baz'] | default('DEFAULT') == 'DEFAULT' + - dict_var['bar']['baz']['abc'] is not defined + - dict_var['bar']['baz']['abc'] | default('DEFAULT') == 'DEFAULT' + - dict_var['baz'] is not defined + - dict_var['baz']['abc'] is not defined + - dict_var['baz']['abc'] | default('DEFAULT') == 'DEFAULT' + - list_var[0] is defined + - list_var[1] is not defined + - list_var[0]['foo'] is defined + - list_var[0]['foo']['bar'] is not defined + - list_var[0]['foo']['bar'] | default('DEFAULT') == 'DEFAULT' + - list_var[1]['foo'] is not defined + - list_var[1]['foo'] | default('DEFAULT') == 'DEFAULT' + - dict_var['bar'].baz is not defined + - dict_var['bar'].baz | default('DEFAULT') == 'DEFAULT' + +- template: + src: template_destpath_test.j2 + dest: "{{ output_dir }}/template_destpath.templated" + +- copy: + content: "{{ output_dir}}/template_destpath.templated\n" + dest: "{{ output_dir }}/template_destpath.expected" + +- name: compare templated file to known good template_destpath + shell: diff -uw {{output_dir}}/template_destpath.templated {{output_dir}}/template_destpath.expected + register: diff_result + +- name: verify templated template_destpath matches known good + assert: + that: + - 'diff_result.stdout == ""' + - "diff_result.rc == 0" + +- debug: + msg: "{{ 'x' in y }}" + ignore_errors: yes + register: error + +- name: check that proper error message is emitted when in operator is used + assert: + that: "\"'y' is undefined\" in error.msg" + +- template: + src: template_import_macro_globals.j2 + dest: "{{ output_dir }}/template_import_macro_globals.templated" + +- command: "cat {{ output_dir }}/template_import_macro_globals.templated" + register: out + +- assert: + that: + - out.stdout == "bar=lookedup_bar" + +# aliases file requires root for template tests so this should be safe +- import_tasks: backup_test.yml + +- name: test STRING_TYPE_FILTERS + copy: + content: "{{ a_dict | to_nice_json(indent=(indent_value|int))}}\n" + dest: "{{ output_dir }}/string_type_filters.templated" + vars: + a_dict: + foo: bar + foobar: 1 + indent_value: 2 + +- name: copy known good string_type_filters.expected into place + copy: + src: string_type_filters.expected + dest: "{{ output_dir }}/string_type_filters.expected" + +- command: "diff {{ output_dir }}/string_type_filters.templated {{ output_dir}}/string_type_filters.expected" + register: out + +- assert: + that: + - out.rc == 0 + +- template: + src: empty_template.j2 + dest: "{{ output_dir }}/empty_template.templated" + +- assert: + that: + - test + vars: + test: "{{ lookup('file', '{{ output_dir }}/empty_template.templated')|length == 0 }}" + +- name: test jinja2 override without colon throws proper error + block: + - template: + src: override_separator.j2 + dest: "{{ output_dir }}/override_separator.templated" + - assert: + that: + - False + rescue: + - assert: + that: + - "'failed to parse jinja2 override' in ansible_failed_result.msg" + +- name: test jinja2 override with colon in value + template: + src: override_colon_value.j2 + dest: "{{ output_dir }}/override_colon_value.templated" + ignore_errors: yes + register: override_colon_value_task + +- copy: + src: override_colon_value.expected + dest: "{{output_dir}}/override_colon_value.expected" + +- command: "diff {{ output_dir }}/override_colon_value.templated {{ output_dir}}/override_colon_value.expected" + register: override_colon_value_diff + +- assert: + that: + - override_colon_value_task is success + - override_colon_value_diff.rc == 0 + +- assert: + that: + - data_not_converted | type_debug == 'NativeJinjaUnsafeText' + - data_converted | type_debug == 'dict' + vars: + data_not_converted: "{{ lookup('template', 'json_macro.j2', convert_data=False) }}" + data_converted: "{{ lookup('template', 'json_macro.j2') }}" + +- name: Test convert_data is correctly set to True for nested vars evaluation + debug: + msg: "{{ lookup('template', 'indirect_dict.j2', convert_data=False) }}" + vars: + d: + foo: bar + v: "{{ d }}" diff --git a/test/integration/targets/template/template.yml b/test/integration/targets/template/template.yml new file mode 100644 index 0000000..d33293b --- /dev/null +++ b/test/integration/targets/template/template.yml @@ -0,0 +1,4 @@ +- hosts: testhost + gather_facts: yes + roles: + - { role: template } diff --git a/test/integration/targets/template/templates/6653-include.j2 b/test/integration/targets/template/templates/6653-include.j2 new file mode 100644 index 0000000..26443b1 --- /dev/null +++ b/test/integration/targets/template/templates/6653-include.j2 @@ -0,0 +1 @@ +{{ x }} diff --git a/test/integration/targets/template/templates/6653.j2 b/test/integration/targets/template/templates/6653.j2 new file mode 100644 index 0000000..8026a79 --- /dev/null +++ b/test/integration/targets/template/templates/6653.j2 @@ -0,0 +1,4 @@ +{% for x in mylist %} +{{ x }} +{% include '6653-include.j2' with context %} +{% endfor %} diff --git a/test/integration/targets/template/templates/72262-included.j2 b/test/integration/targets/template/templates/72262-included.j2 new file mode 100644 index 0000000..35700cb --- /dev/null +++ b/test/integration/targets/template/templates/72262-included.j2 @@ -0,0 +1 @@ +{{ vars.test }} diff --git a/test/integration/targets/template/templates/72262-vars.j2 b/test/integration/targets/template/templates/72262-vars.j2 new file mode 100644 index 0000000..6ef9220 --- /dev/null +++ b/test/integration/targets/template/templates/72262-vars.j2 @@ -0,0 +1 @@ +{% set test = "I'm test variable" %} diff --git a/test/integration/targets/template/templates/72262.j2 b/test/integration/targets/template/templates/72262.j2 new file mode 100644 index 0000000..b72be0d --- /dev/null +++ b/test/integration/targets/template/templates/72262.j2 @@ -0,0 +1,3 @@ +{% import '72262-vars.j2' as vars with context %} +{% macro included() %}{% include '72262-included.j2' %}{% endmacro %} +{{ included()|indent }} diff --git a/test/integration/targets/template/templates/72615-macro-nested.j2 b/test/integration/targets/template/templates/72615-macro-nested.j2 new file mode 100644 index 0000000..c47a499 --- /dev/null +++ b/test/integration/targets/template/templates/72615-macro-nested.j2 @@ -0,0 +1,4 @@ +{% macro print_context_vars_nested(value) %} +foo: {{ foo }} +bar: {{ value }} +{% endmacro %} diff --git a/test/integration/targets/template/templates/72615-macro.j2 b/test/integration/targets/template/templates/72615-macro.j2 new file mode 100644 index 0000000..328c271 --- /dev/null +++ b/test/integration/targets/template/templates/72615-macro.j2 @@ -0,0 +1,8 @@ +{% macro print_context_vars(value) %} +{{ foo }} +{{ value }} +{% set foo = "template-nested-level-foo" %} +{% set bar = "template-nested-level-bar" %} +{% from '72615-macro-nested.j2' import print_context_vars_nested with context %} +{{ print_context_vars_nested(bar) }} +{% endmacro %} diff --git a/test/integration/targets/template/templates/72615.j2 b/test/integration/targets/template/templates/72615.j2 new file mode 100644 index 0000000..b79f88e --- /dev/null +++ b/test/integration/targets/template/templates/72615.j2 @@ -0,0 +1,4 @@ +{% set foo = "template-level-foo" %} +{% set bar = "template-level-bar" %} +{% from '72615-macro.j2' import print_context_vars with context %} +{{ print_context_vars(bar) }} diff --git a/test/integration/targets/template/templates/bar b/test/integration/targets/template/templates/bar new file mode 100644 index 0000000..2b60207 --- /dev/null +++ b/test/integration/targets/template/templates/bar @@ -0,0 +1 @@ +Goodbye diff --git a/test/integration/targets/template/templates/café.j2 b/test/integration/targets/template/templates/café.j2 new file mode 100644 index 0000000..ef7e08e --- /dev/null +++ b/test/integration/targets/template/templates/café.j2 @@ -0,0 +1 @@ +{{ ansible_managed }} diff --git a/test/integration/targets/template/templates/custom_comment_string.j2 b/test/integration/targets/template/templates/custom_comment_string.j2 new file mode 100644 index 0000000..db0af48 --- /dev/null +++ b/test/integration/targets/template/templates/custom_comment_string.j2 @@ -0,0 +1,3 @@ +Before +[# Test comment_start_string #] +After diff --git a/test/integration/targets/template/templates/empty_template.j2 b/test/integration/targets/template/templates/empty_template.j2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/integration/targets/template/templates/empty_template.j2 diff --git a/test/integration/targets/template/templates/encoding_1252.j2 b/test/integration/targets/template/templates/encoding_1252.j2 new file mode 100644 index 0000000..0d3cc35 --- /dev/null +++ b/test/integration/targets/template/templates/encoding_1252.j2 @@ -0,0 +1 @@ +windows-1252 Special Characters: €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ diff --git a/test/integration/targets/template/templates/foo.j2 b/test/integration/targets/template/templates/foo.j2 new file mode 100644 index 0000000..22187f9 --- /dev/null +++ b/test/integration/targets/template/templates/foo.j2 @@ -0,0 +1,3 @@ +{{ templated_var }} + +{{ templated_dict | to_nice_json }} diff --git a/test/integration/targets/template/templates/foo2.j2 b/test/integration/targets/template/templates/foo2.j2 new file mode 100644 index 0000000..e6e3485 --- /dev/null +++ b/test/integration/targets/template/templates/foo2.j2 @@ -0,0 +1,3 @@ +BEGIN +{{ templated_var }} +END diff --git a/test/integration/targets/template/templates/foo3.j2 b/test/integration/targets/template/templates/foo3.j2 new file mode 100644 index 0000000..710d55a --- /dev/null +++ b/test/integration/targets/template/templates/foo3.j2 @@ -0,0 +1,3 @@ +BEGIN +[% templated_var %] +END diff --git a/test/integration/targets/template/templates/for_loop.j2 b/test/integration/targets/template/templates/for_loop.j2 new file mode 100644 index 0000000..49fa412 --- /dev/null +++ b/test/integration/targets/template/templates/for_loop.j2 @@ -0,0 +1,4 @@ +{% for par_var in parent_vars %} +{% include 'for_loop_include.j2' %} + +{% endfor %} diff --git a/test/integration/targets/template/templates/for_loop_include.j2 b/test/integration/targets/template/templates/for_loop_include.j2 new file mode 100644 index 0000000..b1a0ad7 --- /dev/null +++ b/test/integration/targets/template/templates/for_loop_include.j2 @@ -0,0 +1,3 @@ +{% if par_var is defined %} +{% include 'for_loop_include_nested.j2' %} +{% endif %} diff --git a/test/integration/targets/template/templates/for_loop_include_nested.j2 b/test/integration/targets/template/templates/for_loop_include_nested.j2 new file mode 100644 index 0000000..368bce4 --- /dev/null +++ b/test/integration/targets/template/templates/for_loop_include_nested.j2 @@ -0,0 +1 @@ +{{ par_var }} diff --git a/test/integration/targets/template/templates/import_as.j2 b/test/integration/targets/template/templates/import_as.j2 new file mode 100644 index 0000000..b06f1be --- /dev/null +++ b/test/integration/targets/template/templates/import_as.j2 @@ -0,0 +1,4 @@ +{% import 'qux' as qux %} +hello world import as +{{ qux.wibble }} +{% include 'bar' %} diff --git a/test/integration/targets/template/templates/import_as_with_context.j2 b/test/integration/targets/template/templates/import_as_with_context.j2 new file mode 100644 index 0000000..3dd806a --- /dev/null +++ b/test/integration/targets/template/templates/import_as_with_context.j2 @@ -0,0 +1,3 @@ +{% import 'qux' as qux with context %} +hello world as qux with context +{{ qux.wibble }} diff --git a/test/integration/targets/template/templates/import_with_context.j2 b/test/integration/targets/template/templates/import_with_context.j2 new file mode 100644 index 0000000..104e68b --- /dev/null +++ b/test/integration/targets/template/templates/import_with_context.j2 @@ -0,0 +1,4 @@ +{% import 'qux' as qux with context %} +hello world with context +{{ qux.wibble }} +{% include 'bar' %} diff --git a/test/integration/targets/template/templates/indirect_dict.j2 b/test/integration/targets/template/templates/indirect_dict.j2 new file mode 100644 index 0000000..3124371 --- /dev/null +++ b/test/integration/targets/template/templates/indirect_dict.j2 @@ -0,0 +1 @@ +{{ v.foo }} diff --git a/test/integration/targets/template/templates/json_macro.j2 b/test/integration/targets/template/templates/json_macro.j2 new file mode 100644 index 0000000..080f164 --- /dev/null +++ b/test/integration/targets/template/templates/json_macro.j2 @@ -0,0 +1,2 @@ +{% macro m() %}{{ {"foo":"bar"} }}{% endmacro %} +{{ m() }} diff --git a/test/integration/targets/template/templates/lstrip_blocks.j2 b/test/integration/targets/template/templates/lstrip_blocks.j2 new file mode 100644 index 0000000..d572da6 --- /dev/null +++ b/test/integration/targets/template/templates/lstrip_blocks.j2 @@ -0,0 +1,8 @@ +{% set hello_world="hello world" %} +{% for i in [1, 2, 3] %} + {% if loop.first %} +{{hello_world}} + {% else %} +{{hello_world}} + {% endif %} +{% endfor %} diff --git a/test/integration/targets/template/templates/macro_using_globals.j2 b/test/integration/targets/template/templates/macro_using_globals.j2 new file mode 100644 index 0000000..d8d0626 --- /dev/null +++ b/test/integration/targets/template/templates/macro_using_globals.j2 @@ -0,0 +1,3 @@ +{% macro foo(bar) -%} +{{ bar }}={{ lookup('lines', 'echo lookedup_bar') }} +{%- endmacro %} diff --git a/test/integration/targets/template/templates/override_colon_value.j2 b/test/integration/targets/template/templates/override_colon_value.j2 new file mode 100644 index 0000000..2ca9bb8 --- /dev/null +++ b/test/integration/targets/template/templates/override_colon_value.j2 @@ -0,0 +1,4 @@ +#jinja2: line_statement_prefix:":" +: if true +foo +: endif diff --git a/test/integration/targets/template/templates/override_separator.j2 b/test/integration/targets/template/templates/override_separator.j2 new file mode 100644 index 0000000..7589cc3 --- /dev/null +++ b/test/integration/targets/template/templates/override_separator.j2 @@ -0,0 +1 @@ +#jinja2: lstrip_blocks=True diff --git a/test/integration/targets/template/templates/parent.j2 b/test/integration/targets/template/templates/parent.j2 new file mode 100644 index 0000000..99a8e4c --- /dev/null +++ b/test/integration/targets/template/templates/parent.j2 @@ -0,0 +1,3 @@ +{% for parent_item in parent_vars %} +{% include "subtemplate.j2" %} +{% endfor %} diff --git a/test/integration/targets/template/templates/qux b/test/integration/targets/template/templates/qux new file mode 100644 index 0000000..d8cd22e --- /dev/null +++ b/test/integration/targets/template/templates/qux @@ -0,0 +1 @@ +{% set wibble = "WIBBLE" %} diff --git a/test/integration/targets/template/templates/short.j2 b/test/integration/targets/template/templates/short.j2 new file mode 100644 index 0000000..55aab8f --- /dev/null +++ b/test/integration/targets/template/templates/short.j2 @@ -0,0 +1 @@ +{{ templated_var }} diff --git a/test/integration/targets/template/templates/subtemplate.j2 b/test/integration/targets/template/templates/subtemplate.j2 new file mode 100644 index 0000000..f359bf2 --- /dev/null +++ b/test/integration/targets/template/templates/subtemplate.j2 @@ -0,0 +1,2 @@ +{{ parent_item }} + diff --git a/test/integration/targets/template/templates/template_destpath_test.j2 b/test/integration/targets/template/templates/template_destpath_test.j2 new file mode 100644 index 0000000..1d21d8c --- /dev/null +++ b/test/integration/targets/template/templates/template_destpath_test.j2 @@ -0,0 +1 @@ +{{ template_destpath }} diff --git a/test/integration/targets/template/templates/template_import_macro_globals.j2 b/test/integration/targets/template/templates/template_import_macro_globals.j2 new file mode 100644 index 0000000..9b9a9c6 --- /dev/null +++ b/test/integration/targets/template/templates/template_import_macro_globals.j2 @@ -0,0 +1,2 @@ +{% from 'macro_using_globals.j2' import foo %} +{{ foo('bar') }} diff --git a/test/integration/targets/template/templates/trim_blocks.j2 b/test/integration/targets/template/templates/trim_blocks.j2 new file mode 100644 index 0000000..824a0a0 --- /dev/null +++ b/test/integration/targets/template/templates/trim_blocks.j2 @@ -0,0 +1,4 @@ +{% if True %} +Hello world +{% endif %} +Goodbye diff --git a/test/integration/targets/template/templates/unused_vars_include.j2 b/test/integration/targets/template/templates/unused_vars_include.j2 new file mode 100644 index 0000000..457cbbc --- /dev/null +++ b/test/integration/targets/template/templates/unused_vars_include.j2 @@ -0,0 +1 @@ +{{ var_set_in_template }} diff --git a/test/integration/targets/template/templates/unused_vars_template.j2 b/test/integration/targets/template/templates/unused_vars_template.j2 new file mode 100644 index 0000000..28afc90 --- /dev/null +++ b/test/integration/targets/template/templates/unused_vars_template.j2 @@ -0,0 +1,2 @@ +{% set var_set_in_template=test_var %} +{% include "unused_vars_include.j2" %} diff --git a/test/integration/targets/template/undefined_in_import-import.j2 b/test/integration/targets/template/undefined_in_import-import.j2 new file mode 100644 index 0000000..fbb97b0 --- /dev/null +++ b/test/integration/targets/template/undefined_in_import-import.j2 @@ -0,0 +1 @@ +{{ undefined_variable }} diff --git a/test/integration/targets/template/undefined_in_import.j2 b/test/integration/targets/template/undefined_in_import.j2 new file mode 100644 index 0000000..619e4f7 --- /dev/null +++ b/test/integration/targets/template/undefined_in_import.j2 @@ -0,0 +1 @@ +{% import 'undefined_in_import-import.j2' as t %} diff --git a/test/integration/targets/template/undefined_in_import.yml b/test/integration/targets/template/undefined_in_import.yml new file mode 100644 index 0000000..62f60d6 --- /dev/null +++ b/test/integration/targets/template/undefined_in_import.yml @@ -0,0 +1,11 @@ +- hosts: localhost + gather_facts: false + tasks: + - debug: + msg: "{{ lookup('template', 'undefined_in_import.j2') }}" + ignore_errors: true + register: res + + - assert: + that: + - "\"'undefined_variable' is undefined\" in res.msg" diff --git a/test/integration/targets/template/undefined_var_info.yml b/test/integration/targets/template/undefined_var_info.yml new file mode 100644 index 0000000..b96a58d --- /dev/null +++ b/test/integration/targets/template/undefined_var_info.yml @@ -0,0 +1,15 @@ +- hosts: localhost + gather_facts: no + vars: + foo: [] + bar: "{{ foo[0] }}" + tasks: + - debug: + msg: "{{ bar }}" + register: result + ignore_errors: yes + + - assert: + that: + - '"foo[0]" in result.msg' + - '"object has no element 0" in result.msg' diff --git a/test/integration/targets/template/unsafe.yml b/test/integration/targets/template/unsafe.yml new file mode 100644 index 0000000..bef9a4b --- /dev/null +++ b/test/integration/targets/template/unsafe.yml @@ -0,0 +1,64 @@ +- hosts: localhost + gather_facts: false + vars: + nottemplated: this should not be seen + imunsafe: !unsafe '{{ nottemplated }}' + tasks: + + - set_fact: + this_was_unsafe: > + {{ imunsafe }} + + - set_fact: + this_always_safe: '{{ imunsafe }}' + + - name: ensure nothing was templated + assert: + that: + - this_always_safe == imunsafe + - imunsafe == this_was_unsafe.strip() + + +- hosts: localhost + gather_facts: false + vars: + output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}" + tasks: + - set_fact: + unsafe_foo: "{{ lookup('list', var0) }}" + vars: + var0: "{{ var1 }}" + var1: + - unsafe + + - assert: + that: + - "{{ unsafe_foo[0] | type_debug == 'AnsibleUnsafeText' }}" + + - block: + - copy: + dest: "{{ file_name }}" + content: !unsafe "{{ i_should_not_be_templated }}" + + - set_fact: + file_content: "{{ lookup('file', file_name) }}" + + - assert: + that: + - not file_content is contains('unsafe') + + - set_fact: + file_content: "{{ lookup('file', file_name_tmpl) }}" + vars: + file_name_tmpl: "{{ file_name }}" + + - assert: + that: + - not file_content is contains('unsafe') + vars: + file_name: "{{ output_dir }}/unsafe_file" + i_should_not_be_templated: unsafe + always: + - file: + dest: "{{ file_name }}" + state: absent diff --git a/test/integration/targets/template/unused_vars_include.yml b/test/integration/targets/template/unused_vars_include.yml new file mode 100644 index 0000000..ff31b70 --- /dev/null +++ b/test/integration/targets/template/unused_vars_include.yml @@ -0,0 +1,8 @@ +- hosts: localhost + gather_facts: no + vars: + test_var: foo + unused_var: "{{ undefined_var }}" + tasks: + - debug: + msg: "{{ lookup('template', 'unused_vars_template.j2') }}" diff --git a/test/integration/targets/template/vars/main.yml b/test/integration/targets/template/vars/main.yml new file mode 100644 index 0000000..9d45cf2 --- /dev/null +++ b/test/integration/targets/template/vars/main.yml @@ -0,0 +1,20 @@ +templated_var: templated_var_loaded + +number_var: 5 +string_num: "5" +bool_var: true +part_1: 1 +part_2: "Foo" +null_type: !!null + +templated_dict: + number: "{{ number_var }}" + string_num: "{{ string_num }}" + null_type: "{{ null_type }}" + bool: "{{ bool_var }}" + multi_part: "{{ part_1 }}{{ part_2 }}" + +parent_vars: +- foo +- bar +- bam diff --git a/test/integration/targets/template_jinja2_non_native/46169.yml b/test/integration/targets/template_jinja2_non_native/46169.yml new file mode 100644 index 0000000..4dc3dc0 --- /dev/null +++ b/test/integration/targets/template_jinja2_non_native/46169.yml @@ -0,0 +1,31 @@ +- hosts: localhost + gather_facts: no + tasks: + - set_fact: + output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}" + + - template: + src: templates/46169.json.j2 + dest: "{{ output_dir }}/result.json" + + - command: "diff templates/46169.json.j2 {{ output_dir }}/result.json" + register: diff_result + + - assert: + that: + - diff_result.stdout == "" + + - block: + - set_fact: + non_native_lookup: "{{ lookup('template', 'templates/46169.json.j2') }}" + + - assert: + that: + - non_native_lookup | type_debug == 'NativeJinjaUnsafeText' + + - set_fact: + native_lookup: "{{ lookup('template', 'templates/46169.json.j2', jinja2_native=true) }}" + + - assert: + that: + - native_lookup | type_debug == 'dict' diff --git a/test/integration/targets/template_jinja2_non_native/aliases b/test/integration/targets/template_jinja2_non_native/aliases new file mode 100644 index 0000000..1d28bdb --- /dev/null +++ b/test/integration/targets/template_jinja2_non_native/aliases @@ -0,0 +1,2 @@ +shippable/posix/group5 +context/controller diff --git a/test/integration/targets/template_jinja2_non_native/runme.sh b/test/integration/targets/template_jinja2_non_native/runme.sh new file mode 100755 index 0000000..fe9d495 --- /dev/null +++ b/test/integration/targets/template_jinja2_non_native/runme.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -eux + +export ANSIBLE_JINJA2_NATIVE=1 +ansible-playbook 46169.yml -v "$@" +unset ANSIBLE_JINJA2_NATIVE diff --git a/test/integration/targets/template_jinja2_non_native/templates/46169.json.j2 b/test/integration/targets/template_jinja2_non_native/templates/46169.json.j2 new file mode 100644 index 0000000..a4fc3f6 --- /dev/null +++ b/test/integration/targets/template_jinja2_non_native/templates/46169.json.j2 @@ -0,0 +1,3 @@ +{ + "key": "bar" +} |