diff --git a/changelogs/fragments/loop-cache-fix.yaml b/changelogs/fragments/loop-cache-fix.yaml new file mode 100644 index 00000000000..9d0c6000c2e --- /dev/null +++ b/changelogs/fragments/loop-cache-fix.yaml @@ -0,0 +1,2 @@ +bugfixes: +- loop - Ensure we only cache the loop when the task had a loop and delegate_to was templated (https://github.com/ansible/ansible/issues/44874) diff --git a/lib/ansible/vars/manager.py b/lib/ansible/vars/manager.py index 7ac85f5a25d..ebbfa6aedcb 100644 --- a/lib/ansible/vars/manager.py +++ b/lib/ansible/vars/manager.py @@ -494,6 +494,7 @@ class VariableManager: templar = Templar(loader=self._loader, variables=vars_copy) items = [] + has_loop = True if task.loop_with is not None: if task.loop_with in lookup_loader: try: @@ -509,6 +510,7 @@ class VariableManager: elif task.loop is not None: items = templar.template(task.loop) else: + has_loop = False items = [None] delegated_host_vars = dict() @@ -583,7 +585,7 @@ class VariableManager: include_hostvars=False, ) - if cache_items: + if has_loop and cache_items: # delegate_to templating produced a change, update task.loop with templated items, # this ensures that delegate_to+loop doesn't produce different results than TaskExecutor # which may reprocess the loop diff --git a/test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml b/test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml index b43e884a0c6..4513228614e 100644 --- a/test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml +++ b/test/integration/targets/delegate_to/test_delegate_to_loop_randomness.yml @@ -7,6 +7,7 @@ add_host: name: "foo{{item}}" groups: foo + ansible_connection: local loop: "{{ range(10)|list }}" # We expect all of the next 3 runs to succeeed @@ -56,3 +57,16 @@ - "{{ (result1.results|first) is successful }}" - "{{ (result2.results|first) is successful }}" - "{{ (result3.results|first) is successful }}" + + - name: Set delegate + set_fact: + _delegate: '{{ groups.foo[0] }}' + + - command: "true" + delegate_to: "{{ _delegate }}" + register: result + + - assert: + that: + - result.stdout is defined + - result.results is undefined