Wrap all results, regardless of register, except for actions with clean facts (#73161)

* Wrap all results, regardless of register, except for actions with clean facts. Fixes #21088

* ci_complete

* Add tests

* Add clog frag
This commit is contained in:
Matt Martz 2021-06-04 09:40:53 -05:00 committed by GitHub
parent e70fc88656
commit ffa548503d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 3 deletions

View file

@ -0,0 +1,4 @@
bugfixes:
- register - Ensure that ``register`` used on ``set_fact`` or ``include_vars``
does not automatically wrap the facts as unsafe.
(https://github.com/ansible/ansible/issues/21088)

View file

@ -603,13 +603,16 @@ class TaskExecutor:
# preserve no log # preserve no log
result["_ansible_no_log"] = self._play_context.no_log result["_ansible_no_log"] = self._play_context.no_log
if self._task.action not in C._ACTION_WITH_CLEAN_FACTS:
result = wrap_var(result)
# update the local copy of vars with the registered value, if specified, # update the local copy of vars with the registered value, if specified,
# or any facts which may have been generated by the module execution # or any facts which may have been generated by the module execution
if self._task.register: if self._task.register:
if not isidentifier(self._task.register): if not isidentifier(self._task.register):
raise AnsibleError("Invalid variable name in 'register' specified: '%s'" % self._task.register) raise AnsibleError("Invalid variable name in 'register' specified: '%s'" % self._task.register)
vars_copy[self._task.register] = result = wrap_var(result) vars_copy[self._task.register] = result
if self._task.async_val > 0: if self._task.async_val > 0:
if self._task.poll > 0 and not result.get('skipped') and not result.get('failed'): if self._task.poll > 0 and not result.get('skipped') and not result.get('failed'):
@ -661,12 +664,15 @@ class TaskExecutor:
if 'changed' not in result: if 'changed' not in result:
result['changed'] = False result['changed'] = False
if self._task.action not in C._ACTION_WITH_CLEAN_FACTS:
result = wrap_var(result)
# re-update the local copy of vars with the registered value, if specified, # re-update the local copy of vars with the registered value, if specified,
# or any facts which may have been generated by the module execution # or any facts which may have been generated by the module execution
# This gives changed/failed_when access to additional recently modified # This gives changed/failed_when access to additional recently modified
# attributes of result # attributes of result
if self._task.register: if self._task.register:
vars_copy[self._task.register] = result = wrap_var(result) vars_copy[self._task.register] = result
# if we didn't skip this task, use the helpers to evaluate the changed/ # if we didn't skip this task, use the helpers to evaluate the changed/
# failed_when properties # failed_when properties
@ -708,10 +714,13 @@ class TaskExecutor:
result['attempts'] = retries - 1 result['attempts'] = retries - 1
result['failed'] = True result['failed'] = True
if self._task.action not in C._ACTION_WITH_CLEAN_FACTS:
result = wrap_var(result)
# do the final update of the local variables here, for both registered # do the final update of the local variables here, for both registered
# values and any facts which may have been created # values and any facts which may have been created
if self._task.register: if self._task.register:
variables[self._task.register] = result = wrap_var(result) variables[self._task.register] = result
if 'ansible_facts' in result and self._task.action not in C._ACTION_DEBUG: if 'ansible_facts' in result and self._task.action not in C._ACTION_DEBUG:
if self._task.action in C._ACTION_WITH_CLEAN_FACTS: if self._task.action in C._ACTION_WITH_CLEAN_FACTS:

View file

@ -57,6 +57,8 @@
include_vars: include_vars:
dir: vars dir: vars
extensions: ['', 'yaml', 'yml', 'json'] extensions: ['', 'yaml', 'yml', 'json']
ignore_files:
- no_auto_unsafe.yml
register: include_every_dir register: include_every_dir
- name: verify that the correct files have been loaded and overwrite based on alphabetical order - name: verify that the correct files have been loaded and overwrite based on alphabetical order
@ -78,6 +80,7 @@
ignore_files: ignore_files:
- webapp.yml - webapp.yml
- file_without_extension - file_without_extension
- no_auto_unsafe.yml
register: include_without_webapp register: include_without_webapp
- name: verify that the webapp.yml file was not included - name: verify that the webapp.yml file was not included
@ -162,3 +165,11 @@
that: that:
- "'my_custom_service' == service_name_fqcn" - "'my_custom_service' == service_name_fqcn"
- "'my_custom_service' == service_name_tmpl_fqcn" - "'my_custom_service' == service_name_tmpl_fqcn"
- include_vars:
file: no_auto_unsafe.yml
register: baz
- assert:
that:
- baz.ansible_facts.foo|type_debug != "AnsibleUnsafeText"

View file

@ -0,0 +1 @@
foo: bar

View file

@ -31,3 +31,6 @@ ANSIBLE_JINJA2_NATIVE=1 ansible-playbook -v set_fact_bool_conv_jinja2_native.yml
# Test parsing of values when using an empty string as a key # Test parsing of values when using an empty string as a key
ansible-playbook -i inventory set_fact_empty_str_key.yml ansible-playbook -i inventory set_fact_empty_str_key.yml
# https://github.com/ansible/ansible/issues/21088
ansible-playbook -i inventory "$@" set_fact_auto_unsafe.yml

View file

@ -0,0 +1,10 @@
- hosts: localhost
gather_facts: false
tasks:
- set_fact:
foo: bar
register: baz
- assert:
that:
- baz.ansible_facts.foo|type_debug != "AnsibleUnsafeText"