Skip to content

Commit 33bceb6

Browse files
committed
issue #602: recover task_vars for synchronize and meta: reset_connection
1 parent 6b4bcf4 commit 33bceb6

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

ansible_mitogen/connection.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import mitogen.fork
4747
import mitogen.utils
4848

49+
import ansible_mitogen.mixins
4950
import ansible_mitogen.parsing
5051
import ansible_mitogen.process
5152
import ansible_mitogen.services
@@ -533,6 +534,47 @@ def on_action_run(self, task_vars, delegate_to_hostname, loader_basedir):
533534
self.loader_basedir = loader_basedir
534535
self._mitogen_reset(mode='put')
535536

537+
def _get_task_vars(self):
538+
"""
539+
More information is needed than normally provided to an Ansible
540+
connection. For proxied connections, intermediary configuration must
541+
be inferred, and for any connection the configured Python interpreter
542+
must be known.
543+
544+
There is no clean way to access this information that would not deviate
545+
from the running Ansible version. The least invasive method known is to
546+
reuse the running task's task_vars dict.
547+
548+
This method walks the stack to find task_vars of the Action plugin's
549+
run(), or if no Action is present, from Strategy's _execute_meta(), as
550+
in the case of 'meta: reset_connection'. The stack is walked in
551+
addition to subclassing Action.run()/on_action_run(), as it is possible
552+
for new connections to be constructed in addition to the preconstructed
553+
connection passed into any running action.
554+
"""
555+
f = sys._getframe()
556+
557+
while f:
558+
if f.f_code.co_name == 'run':
559+
f_locals = f.f_locals
560+
f_self = f_locals.get('self')
561+
if isinstance(f_self, ansible_mitogen.mixins.ActionModuleMixin):
562+
task_vars = f_locals.get('task_vars')
563+
if task_vars:
564+
LOG.debug('recovered task_vars from Action')
565+
return task_vars
566+
elif f.f_code.co_name == '_execute_meta':
567+
f_all_vars = f.f_locals.get('all_vars')
568+
if isinstance(f_all_vars, dict):
569+
LOG.debug('recovered task_vars from meta:')
570+
return f_all_vars
571+
572+
f = f.f_back
573+
574+
LOG.warning('could not recover task_vars. This means some connection '
575+
'settings may erroneously be reset to their defaults. '
576+
'Please report a bug if you encounter this message.')
577+
536578
def get_task_var(self, key, default=None):
537579
"""
538580
Fetch the value of a task variable related to connection configuration,
@@ -544,12 +586,13 @@ def get_task_var(self, key, default=None):
544586
does not make sense to extract connection-related configuration for the
545587
delegated-to machine from them.
546588
"""
547-
if self._task_vars:
589+
task_vars = self._task_vars or self._get_task_vars()
590+
if task_vars is not None:
548591
if self.delegate_to_hostname is None:
549-
if key in self._task_vars:
550-
return self._task_vars[key]
592+
if key in task_vars:
593+
return task_vars[key]
551594
else:
552-
delegated_vars = self._task_vars['ansible_delegated_vars']
595+
delegated_vars = task_vars['ansible_delegated_vars']
553596
if self.delegate_to_hostname in delegated_vars:
554597
task_vars = delegated_vars[self.delegate_to_hostname]
555598
if key in task_vars:

0 commit comments

Comments
 (0)