Skip to content

Commit

Permalink
Always set the discovered interpreter on the delegated host (ansible#…
Browse files Browse the repository at this point in the history
…64906)

* Always set the discovered interpreter on the delegated host. Fixes ansible#63180

* Make code a little more generic

* Move code into a function

* Implement some changes based on reviews

* Add changelog fragment
  • Loading branch information
sivel authored Apr 6, 2020
1 parent 318d560 commit 123c624
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
4 changes: 4 additions & 0 deletions changelogs/fragments/64906-always-delegate-fact-prefixes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bugfixes:
- Fact Delegation - Add ability to indicate which facts must always be delegated. Primarily
for ``discovered_interpreter_python`` right now, but extensible later.
(https://github.com/ansible/ansible/issues/61002)
38 changes: 37 additions & 1 deletion lib/ansible/plugins/strategy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@

__all__ = ['StrategyBase']

# This list can be an exact match, or start of string bound
# does not accept regex
ALWAYS_DELEGATE_FACT_PREFIXES = frozenset((
'discovered_interpreter_',
))


class StrategySentinel:
pass
Expand Down Expand Up @@ -389,6 +395,34 @@ def get_delegated_hosts(self, result, task):
host_name = result.get('_ansible_delegated_vars', {}).get('ansible_delegated_host', None)
return [host_name or task.delegate_to]

def _set_always_delegated_facts(self, result, task):
"""Sets host facts for ``delegate_to`` hosts for facts that should
always be delegated
This operation mutates ``result`` to remove the always delegated facts
See ``ALWAYS_DELEGATE_FACT_PREFIXES``
"""
if task.delegate_to is None:
return

facts = result['ansible_facts']
always_keys = set()
_add = always_keys.add
for fact_key in facts:
for always_key in ALWAYS_DELEGATE_FACT_PREFIXES:
if fact_key.startswith(always_key):
_add(fact_key)
if always_keys:
_pop = facts.pop
always_facts = {
'ansible_facts': dict((k, _pop(k)) for k in list(facts) if k in always_keys)
}
host_list = self.get_delegated_hosts(result, task)
_set_host_facts = self._variable_manager.set_host_facts
for target_host in host_list:
_set_host_facts(target_host, always_facts)

@debug_closure
def _process_pending_results(self, iterator, one_pass=False, max_passes=None):
'''
Expand Down Expand Up @@ -606,11 +640,13 @@ def search_handler_blocks_by_name(handler_name, handler_blocks):
self._add_group(original_host, result_item)

if 'ansible_facts' in result_item:

# 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:
host_list = self.get_delegated_hosts(result_item, original_task)
else:
# Set facts that should always be on the delegated hosts
self._set_always_delegated_facts(result_item, original_task)

host_list = self.get_task_hosts(iterator, original_host, original_task)

if original_task.action == 'include_vars':
Expand Down

0 comments on commit 123c624

Please sign in to comment.