-
Notifications
You must be signed in to change notification settings - Fork 23.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using set_fact with delegate_to, delegate_facts and with_items only sets the fact on the first host #20508
Comments
In fact, delegated_facts seams not to work at all with version 2.2.1.0 (at list the way descrubed in Delegation, Rolling Updates, and Local Actions.
Config file: [defaults]
gathering = smart
# le cache nécessite la version 1.8 minimum
fact_caching = jsonfile
fact_caching_connection = facts_cache
fact_caching_timeout = 86400
nocows = 1
retry_files_enabled = False
remote_user = root playbook: ---
- hosts: all
tags: ['always']
gather_facts: no
vars:
debug: false
tasks:
- name: gather facts on all hosts
setup: gather_subset=!all
delegate_to: "{{ item }}"
delegate_facts: true
with_items: "{{ groups['all'] }}"
when: inventory_hostname == ansible_play_hosts[0]
- debug: var=hostvars[item].ansible_fqdn
with_items: "{{ groups['all'] }}" Result with version 2.2.0.0:
Result with 2.2.1.0:
|
I can confirm the issue:
Expected result:
Actual result:
With Ansible 2.1 works as expected |
This is still broken in |
The problem is not really related to the set_fact module itself. Maybe best to involve the person that was responsible of the change ? @jimi-c PS And we should definitely add these (failing) examples to the integration tests too ! |
Since we no longer use a post-validated task in _process_pending_results, we need to be sure to template fields used in original_task as they are raw and may contain variables. This patch also moves the handler tracking to be per-uuid, not per-object. Doing it per-object had implications for the above due to the fact that the copy of the original task is now being used, so the only sure way is to track based on the uuid instead. Fixes #18289 (cherry picked from commit dd0257b)
I added a comment to the responsible changes in the commit ( 2d8ebbf ) that caused this issue. Ansible version: Ansible from source, commit ref: 2d8ebbf - hosts: controller
tasks:
- name: "gather data from nodes"
setup:
delegate_to: "{{ item }}"
delegate_facts: true
with_items: "{{ groups.nodes }}"
- name: "print ipv4s"
debug: var=hostvars[item].ansible_all_ipv4_addresses
with_items: "{{ groups.nodes }}" And using this simplified inventory: controller ansible_connection=local
node1 ansible_ssh_host=172.17.2.11
node2 ansible_ssh_host=172.17.2.12
[nodes]
node1
node2 Result with commit 2d8ebbf:
Result with same commit, but reverted the three lines:
The reverted changes / lines: diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py
index 1d4fee5..7f7a3e6 100644
--- a/lib/ansible/plugins/strategy/__init__.py
+++ b/lib/ansible/plugins/strategy/__init__.py
@@ -483,9 +483,12 @@ class StrategyBase:
# if delegated fact and we are delegating facts, we need to change target host for them
if original_task.delegate_to is not None and original_task.delegate_facts:
+ task_vars = self._variable_manager.get_vars(loader=self._loader, play=iterator._play, host=original_host, task=original_task)
+ self.add_tqm_variables(task_vars, play=iterator._play)
item = result_item.get(loop_var, None)
if item is not None:
task_vars[loop_var] = item
+ templar = Templar(loader=self._loader, variables=task_vars)
host_name = templar.template(original_task.delegate_to)
actual_host = self._inventory.get_host(host_name)
if actual_host is None: |
Our project is still stuck with 2.2.0.0 due to this bug. I finally got around to dig deeper, see pull request #23599 |
This PR seems to be very similar to the change that fixed #17582 and was later removed. |
ansible inventory
ansible.cfg
test.yml
[dot]cache dir contents
last working version:
|
Logic based on Ansible 2.2.0.0 source, code adapted to changes introduced with ansible#22003
In _process_pending_results (strategy/__init__.py), we were using the delegate_to field directly from the original task, which was not being templated correctly. As an alternate to #23599, this patch instead pulls the host name out of the delegated vars passed back in the task result dictionary to avoid having to re-template things. Fixes #23599 Fixes #20508
Closing This TicketHi! We believe the above commit should resolve this problem for you. This will also be included in the next release. If you continue seeing any problems related to this issue, or if you have any further questions, please let us know by stopping by one of the two mailing lists, as appropriate:
Because this project is very active, we're unlikely to see comments made on closed tickets, but the mailing list is a great way to ask questions, or post if you don't think this particular issue is resolved. Thank you! |
In _process_pending_results (strategy/__init__.py), we were using the delegate_to field directly from the original task, which was not being templated correctly. As an alternate to #23599, this patch instead pulls the host name out of the delegated vars passed back in the task result dictionary to avoid having to re-template things. Fixes #23599 Fixes #20508
In _process_pending_results (strategy/__init__.py), we were using the delegate_to field directly from the original task, which was not being templated correctly. As an alternate to #23599, this patch instead pulls the host name out of the delegated vars passed back in the task result dictionary to avoid having to re-template things. Fixes #23599 Fixes #20508 (cherry picked from commit e5cd675)
In _process_pending_results (strategy/__init__.py), we were using the delegate_to field directly from the original task, which was not being templated correctly. As an alternate to ansible#23599, this patch instead pulls the host name out of the delegated vars passed back in the task result dictionary to avoid having to re-template things. Fixes ansible#23599 Fixes ansible#20508
Related to issue ansible#20508, issue ansible#20980 where delegated facts are not set correctly, probably more. Fixed in PR ansible#25880 Use multi-line syntax for all tasks. Cleanup
ISSUE TYPE
COMPONENT NAME
set_fact
ANSIBLE VERSION
CONFIGURATION
OS / ENVIRONMENT
Red Hat Enterprise Linux Client release 7.3 (Maipo)
SUMMARY
In Ansible 2.2.1.0, if you use set_fact, delegate_to and delegate_facts to set facts on several hosts listed in with_items, only the first host in the list will have the fact set. In all other versions of Ansible 2.x, the fact will be set on all hosts.
STEPS TO REPRODUCE
Create a playbook like this:
I am using a simple inventory file:
EXPECTED RESULTS
If I run the playbook with Ansible 2.2.0.0 I get these results:
ACTUAL RESULTS
If I run with Ansible 2.2.1.0, the fact is only set for the first host:
The bug seems to be related to a change to plugins/strategy/init.py here: 2d8ebbf
The text was updated successfully, but these errors were encountered: