- name: Run a module which returns a warning and deprecation warning noisy: register: result - name: Verify the registered module results can be displayed without error debug: var: result - include_tasks: plugin_errors.yml - command: echo {% raw %}{{ foo }}{% endraw %} register: result - assert: that: - result.stdout_lines|first == expected vars: expected: !unsafe '{{ foo }}' - name: Assert that templating treats strings that look like Python as strings (previously some conversions would apply) assert: that: - foo | type_debug == 'str' - | foo == '{"null": null, "true": true, "false": false}' vars: foo: '{{ "" }}{"null": null, "true": true, "false": false}' - name: Ensure that valid Jinja builtin test plugin works even when its name is an invalid Ansible plugin name (1/2) set_fact: foo: '{{ [{"failed": false}] | selectattr("failed", "==", true) }}' - name: Ensure that a non-existent test plugin that is also an invalid Ansible plugin name fails properly (2/2) raw: echo {{ [{}] | selectattr("failed", "asdf ", true) }} ignore_errors: true register: result - assert: that: - result is failed - result.msg is contains("No test named 'asdf '") - name: Ensure that runtime dispatch errors result in a failure debug: msg: "{{ lookup('vars', 'v1', default='', default='') }}" ignore_errors: true register: r - assert: that: - r is failed - "'keyword argument repeated' in r.msg" - name: ensure nested indirect templating is lazy (only recurse to render containers with templated when one is leaving the template system) vars: tripwire_file: "{{ output_dir ~ '/bang' }}" top_level: '{{ intermediate }}' intermediate: '{{ lowest }}' lowest: key1: static data key2: subdict2: unused_value_with_tripwire: '{{ lookup("pipe", "touch " ~ output_dir ~ "/bang") }}' block: - name: ensure tripwire file is missing raw: rm -f {{ tripwire_file }} - name: manipulate a var with nested indirected templates and ensure that only the areas we access are templated set_fact: am_i_lazy: '{{ top_level.key1 }}' - name: check presence of tripwire stat: path: '{{ tripwire_file }}' register: stat_res - assert: that: - am_i_lazy == "static data" - not stat_res.stat.exists # omitting output for brevity in CI - no_log: true block: - name: ensure that `hostvars` gets flattened properly from Templar debug: msg: '{{ hostvars }}' register: hostvars_result - name: ensure that `hostvars['somehost']` gets flattened properly from Templar debug: msg: '{{ hostvars.testhost }}' register: hostvarsvars_result - name: ensure that `vars` gets flattened properly from Templar debug: msg: '{{ vars }}' register: vars_result - assert: that: - hostvars_result.msg.testhost.inventory_hostname == "testhost" - hostvars_result.msg | type_debug == "dict" - hostvarsvars_result.msg.inventory_hostname == "testhost" - hostvarsvars_result.msg | type_debug == "dict" - vars_result.msg.hostvars is defined - vars_result.msg | type_debug == "dict" - vars: task_scalar: i am a scalar task_dict_yaml: scalar_ref: '{{ task_scalar }}' task_dict_jinja: '{{ {"scalar_ref": task_scalar} }}' task_list_yaml: [ '{{ task_scalar }}' ] task_list_jinja: '{{ [ task_scalar ] }}' block: - name: ensure that lazy containers with embedded templates handle equality-ish operators correctly assert: that: - 'task_dict_yaml == {"scalar_ref": "i am a scalar"}' - 'task_dict_jinja == {"scalar_ref": "i am a scalar"}' - task_list_yaml == ["i am a scalar"] - task_list_jinja == ["i am a scalar"] - name: trigger a template cycle that overflows the stack vars: cycle: '{{ cycle }}' raw: echo {{ cycle }} ignore_errors: true register: result - assert: that: - result is failed - result.msg is contains("Recursive loop detected in template") - raw: "{{ '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" - name: test inline list containing a constant template arg to a lookup debug: msg: |- {{ lookup('list', ['{{ 1 }}']) }} register: result failed_when: result.msg != [1] - name: test inline dict containing a constant template arg to a lookup debug: msg: |- {{ lookup('dict', {'key': '{{ 1 }}'}) }} register: result failed_when: result.msg.value != 1 - name: test inline constant template arg to a lookup in a non-optimizable expression vars: echo_me: hi mom debug: msg: |- {{ lookup('pipe', 'echo "{{ echo_me }}"') }} register: result failed_when: result.msg != "hi mom" - name: ensure that embedded template constants are ignored outside conditionals and lookup args raw: echo {{ "{{ 1 }}" }} register: result failed_when: result.stdout is not contains "{" - name: ensure that embedded template constants in locals work in lookup args debug: msg: |- {{ lookup('pipe', 'echo {{ "h" + "i" | string }}') }} register: result - name: ensure that embedded template constants in locals are ignored outside conditionals and lookups raw: |- echo "{% set a = '{{ 1 }}' %}{% set b = '{{ 2 }}' %}{{ a + b }}" register: result failed_when: result.stdout is not contains("{") - name: ensure that embedded template constants in locals do not work in conditional-as-template fallback (pre-2.17 compat) assert: that: |- {% set a = '{{ 1 }}' %} {% set b = '{{ 2 }}' %} {{ a + b == ("{" ~ "{ 1 }}{" ~ "{ 2 }}") }} register: result - name: ensure that embedded non-string templates fail raw: echo {{ {{ 1 }} }} register: result ignore_errors: true - assert: that: - result is failed - result.msg is contains("Syntax error") - vars: dict_with_undecryptable_vault: deeper: vaulted_thing: !vault | $ANSIBLE_VAULT;1.1;AES256 63326561376261613563313535363635306336343061343735343931396538666263326333316135 3364323839336665663238376238336661636630316635360a613537653337363035373261623038 30633437653432623936376239376466316434393134393632313163633965353530376361626564 3262633163333464330a393161353063326562626665333138373839633165376639343166333561 3663 block: - name: undecryptable vault values in a scalar template should trip on JSON serialization debug: msg: '{{ dict_with_undecryptable_vault | to_json }}' ignore_errors: true register: result - assert: that: - result is failed - result.msg is contains("undecryptable variable") - name: undecryptable vault values in a list of templates should trip on JSON serialization debug: msg: - '{{ dict_with_undecryptable_vault | to_json }}' ignore_errors: true register: result - assert: that: - result is failed - result.msg is contains("undecryptable variable") - name: vaulted values are not trusted for templating vars: # value is {{ "not trusted" }} encrypted with "blarblar" vaulted_with_template: !vault | $ANSIBLE_VAULT;1.1;AES256 36306639316132393663356162643765396231396462623962373832643539306635356639366633 6234303731383636623165633330653435336130613361370a373931613335353762376433636263 35363536613933396532636430646337393932393166396133613666386433353932373063356235 3666336365616535610a636534333332633930326331353533626332363263363666373730386264 31643561353465613030343632663036313963363634663231393665316437646530 decrypt_vaulted_value: '{{ vaulted_with_template | unvault("blarblar") }}' debug: var: decrypt_vaulted_value register: vault_value_untrusted - assert: that: - vault_value_untrusted.decrypt_vaulted_value == ('{' ~ '{ "not trusted" }}')