diff --git a/ansible_mitogen/connection.py b/ansible_mitogen/connection.py index 1686cbde..78e0f932 100644 --- a/ansible_mitogen/connection.py +++ b/ansible_mitogen/connection.py @@ -159,6 +159,7 @@ def _connect_ssh(spec): } } + def _connect_buildah(spec): """ Return ContextService arguments for a Buildah connection. @@ -174,6 +175,7 @@ def _connect_buildah(spec): } } + def _connect_docker(spec): """ Return ContextService arguments for a Docker connection. @@ -600,16 +602,33 @@ class Connection(ansible.plugins.connection.ConnectionBase): does not make sense to extract connection-related configuration for the delegated-to machine from them. """ + def _fetch_task_var(task_vars, key): + """ + Special helper func in case vars can be templated + """ + SPECIAL_TASK_VARS = [ + 'ansible_python_interpreter' + ] + if key in task_vars: + val = task_vars[key] + if '{' in str(val) and key in SPECIAL_TASK_VARS: + # template every time rather than storing in a cache + # in case a different template value is used in a different task + val = self.templar.template( + val, + preserve_trailing_newlines=True, + escape_backslashes=False + ) + return val + task_vars = self._get_task_vars() if self.delegate_to_hostname is None: - if key in task_vars: - return task_vars[key] + return _fetch_task_var(task_vars, key) else: delegated_vars = task_vars['ansible_delegated_vars'] if self.delegate_to_hostname in delegated_vars: task_vars = delegated_vars[self.delegate_to_hostname] - if key in task_vars: - return task_vars[key] + return _fetch_task_var(task_vars, key) return default @@ -708,8 +727,8 @@ class Connection(ansible.plugins.connection.ConnectionBase): ) stack += (CONNECTION_METHOD[spec.transport()](spec),) - if spec.become() and ((spec.become_user() != spec.remote_user()) or - C.BECOME_ALLOW_SAME_USER): + if spec.become() and ((spec.become_user() != spec.remote_user()) + or C.BECOME_ALLOW_SAME_USER): stack += (CONNECTION_METHOD[spec.become_method()](spec),) return stack diff --git a/ansible_mitogen/mixins.py b/ansible_mitogen/mixins.py index eee1ecd7..c268f2be 100644 --- a/ansible_mitogen/mixins.py +++ b/ansible_mitogen/mixins.py @@ -87,6 +87,7 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase): that crop up due to this. Mitogen always runs a task completely within the target user account, so it's not a problem for us. """ + def __init__(self, task, connection, *args, **kwargs): """ Verify the received connection is really a Mitogen connection. If not, @@ -103,6 +104,8 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase): if not isinstance(connection, ansible_mitogen.connection.Connection): _, self.__class__ = type(self).__bases__ + connection.templar = self._templar + def run(self, tmp=None, task_vars=None): """ Override run() to notify Connection of task-specific data, so it has a @@ -178,7 +181,7 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase): return os.path.join( self._connection.get_good_temp_dir(), 'ansible_mitogen_action_%016x' % ( - random.getrandbits(8*8), + random.getrandbits(8 * 8), ) ) diff --git a/ansible_mitogen/planner.py b/ansible_mitogen/planner.py index 96b06995..9a5227b9 100644 --- a/ansible_mitogen/planner.py +++ b/ansible_mitogen/planner.py @@ -64,6 +64,7 @@ class Invocation(object): Collect up a module's execution environment then use it to invoke target.run_module() or helpers.run_module_async() in the target context. """ + def __init__(self, action, connection, module_name, module_args, task_vars, templar, env, wrap_async, timeout_secs): #: ActionBase instance invoking the module. Required to access some @@ -104,6 +105,7 @@ class Planner(object): file, indicates whether or not it understands how to run the module, and exports a method to run the module. """ + def __init__(self, invocation): self._inv = invocation @@ -193,6 +195,7 @@ class ScriptPlanner(BinaryPlanner): Common functionality for script module planners -- handle interpreter detection and rewrite. """ + def _rewrite_interpreter(self, path): """ Given the original interpreter binary extracted from the script's @@ -311,10 +314,10 @@ class NewStylePlanner(ScriptPlanner): * the module is known to leak like a sieve. """ return ( - super(NewStylePlanner, self).should_fork() or - (self._inv.task_vars.get('mitogen_task_isolation') == 'fork') or - (self._inv.module_name in self.ALWAYS_FORK_MODULES) or - (len(self.get_module_map()['custom']) > 0) + super(NewStylePlanner, self).should_fork() + or (self._inv.task_vars.get('mitogen_task_isolation') == 'fork') + or (self._inv.module_name in self.ALWAYS_FORK_MODULES) + or (len(self.get_module_map()['custom']) > 0) ) def get_search_path(self): diff --git a/ansible_mitogen/strategy.py b/ansible_mitogen/strategy.py index 8f093999..99d365a7 100644 --- a/ansible_mitogen/strategy.py +++ b/ansible_mitogen/strategy.py @@ -113,6 +113,7 @@ def _patch_awx_callback(): EventContext._local = threading.local() EventContext.add_local = patch_add_local + _patch_awx_callback() @@ -181,6 +182,7 @@ class AnsibleWrappers(object): """ Manage add/removal of various Ansible runtime hooks. """ + def _add_plugin_paths(self): """ Add the Mitogen plug-in directories to the ModuleLoader path, avoiding