Skip to content

Commit

Permalink
unsafe wrapping should only happen for with_ loops (ansible#64401)
Browse files Browse the repository at this point in the history
* unsafe wrapping should only happen for with_ lookups. Fixes ansible#64379. Addresses ansible#64169

* edit porting guide entry

* typo in changelog fragment

* typo

Co-Authored-By: Sandra McCann <[email protected]>

* punctuation

Co-Authored-By: Sandra McCann <[email protected]>
  • Loading branch information
sivel and samccann authored Nov 6, 2019
1 parent c5d6195 commit 254788b
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 8 deletions.
5 changes: 5 additions & 0 deletions changelogs/fragments/64379-no-loop-unsafe.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bugfixes:
- loops - Do not indiscriminately mark loop items as unsafe, only apply unsafe
to ``with_`` style loops. The items from ``loop`` should not be explicitly
wrapped in unsafe. The underlying templating mechanism should dictate this.
(https://github.com/ansible/ansible/issues/64379)
11 changes: 11 additions & 0 deletions docs/docsite/rst/porting_guides/porting_guide_2.9.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,19 @@ This document is part of a collection on porting. The complete list of porting g
Playbook
========

Inventory
---------

* ``hash_behaviour`` now affects inventory sources. If you have it set to ``merge``, the data you get from inventory might change and you will have to update playbooks accordingly. If you're using the default setting (``overwrite``), you will see no changes. Inventory was ignoring this setting.

Loops
-----

Ansible 2.9 handles "unsafe" data more robustly, ensuring that data marked "unsafe" is not templated. In previous versions, Ansible recursively marked all data returned by the direct use of ``lookup()`` as "unsafe", but only marked structured data returned by indirect lookups using ``with_X`` style loops as "unsafe" if the returned elements were strings. Ansible 2.9 treats these two approaches consistently.

As a result, if you use ``with_dict`` to return keys with templatable values, your templates may no longer work as expected in Ansible 2.9.

To allow the old behavior, switch from using ``with_X`` to using ``loop`` with a filter as described at :ref:`migrating_to_loop`.

Command Line
============
Expand Down
7 changes: 1 addition & 6 deletions lib/ansible/executor/task_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def _get_loop_items(self):
setattr(mylookup, '_subdir', subdir + 's')

# run lookup
items = mylookup.run(terms=loop_terms, variables=self._job_vars, wantlist=True)
items = wrap_var(mylookup.run(terms=loop_terms, variables=self._job_vars, wantlist=True))
else:
raise AnsibleError("Unexpected failure in finding the lookup named '%s' in the available lookup plugins" % self._task.loop_with)

Expand All @@ -264,11 +264,6 @@ def _get_loop_items(self):
else:
del self._job_vars[k]

if items:
for idx, item in enumerate(items):
if item is not None and not isinstance(item, AnsibleUnsafe):
items[idx] = wrap_var(item)

return items

def _run_loop(self, items):
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/utils/unsafe_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def _wrap_set(v):


def wrap_var(v):
if isinstance(v, AnsibleUnsafe):
if v is None or isinstance(v, AnsibleUnsafe):
return v

if isinstance(v, Mapping):
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/vars/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ def _get_delegated_vars(self, play, task, existing_variables):
try:
loop_terms = listify_lookup_plugin_terms(terms=task.loop, templar=templar,
loader=self._loader, fail_on_undefined=True, convert_bare=False)
items = lookup_loader.get(task.loop_with, loader=self._loader, templar=templar).run(terms=loop_terms, variables=vars_copy)
items = wrap_var(lookup_loader.get(task.loop_with, loader=self._loader, templar=templar).run(terms=loop_terms, variables=vars_copy))
except AnsibleTemplateError:
# This task will be skipped later due to this, so we just setup
# a dummy array for the later code so it doesn't fail
Expand Down
30 changes: 30 additions & 0 deletions test/integration/targets/loops/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,33 @@
- assert:
that:
- loop_out['results'][1]['ansible_remote_tmp'] == '/tmp/test1'

# https://github.com/ansible/ansible/issues/64169
- include_vars: 64169.yml

- set_fact: "{{ item.key }}={{ hostvars[inventory_hostname][item.value] }}"
with_dict:
foo: __foo

- debug:
var: foo

- assert:
that:
- foo[0] != 'foo1.0'
- foo[0] == unsafe_value
vars:
unsafe_value: !unsafe 'foo{{ version_64169 }}'

- set_fact: "{{ item.key }}={{ hostvars[inventory_hostname][item.value] }}"
loop: "{{ dicty_dict|dict2items }}"
vars:
dicty_dict:
foo: __foo

- debug:
var: foo

- assert:
that:
- foo[0] == 'foo1.0'
2 changes: 2 additions & 0 deletions test/integration/targets/loops/vars/64169.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__foo:
- "foo{{ version_64169 }}"
1 change: 1 addition & 0 deletions test/integration/targets/loops/vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ phrases:
filenames:
- 'data1.txt'
- 'data2.txt'
version_64169: '1.0'

0 comments on commit 254788b

Please sign in to comment.