issue #177: fetch and cache HOME value during connection setup.

This ensures only 1 roundtrip is required for every invocation of
_remote_expand_user().
This commit is contained in:
David Wilson 2018-04-01 15:54:17 +01:00
parent 772e229b7d
commit 6eed3aa1fa
3 changed files with 38 additions and 10 deletions

View File

@ -82,6 +82,9 @@ class Connection(ansible.plugins.connection.ConnectionBase):
#: Set to 'mitogen_ssh_discriminator' by on_action_run() #: Set to 'mitogen_ssh_discriminator' by on_action_run()
mitogen_ssh_discriminator = None mitogen_ssh_discriminator = None
#: Set after connection to the target context's home directory.
_homedir = None
def __init__(self, play_context, new_stdin, original_transport, **kwargs): def __init__(self, play_context, new_stdin, original_transport, **kwargs):
assert ansible_mitogen.process.MuxProcess.unix_listener_path, ( assert ansible_mitogen.process.MuxProcess.unix_listener_path, (
'The "mitogen" connection plug-in may only be instantiated ' 'The "mitogen" connection plug-in may only be instantiated '
@ -125,6 +128,11 @@ class Connection(ansible.plugins.connection.ConnectionBase):
'sudo' 'sudo'
) )
@property
def homedir(self):
self._connect()
return self._homedir
@property @property
def connected(self): def connected(self):
return self.broker is not None return self.broker is not None
@ -232,18 +240,20 @@ class Connection(ansible.plugins.connection.ConnectionBase):
if self.original_transport == 'local': if self.original_transport == 'local':
if self._play_context.become: if self._play_context.become:
self.context = self._connect_sudo(python_path=sys.executable) self.context, self._homedir = self._connect_sudo(
python_path=sys.executable
)
else: else:
self.context = self._connect_local() self.context, self._homedir = self._connect_local()
return return
if self.original_transport == 'docker': if self.original_transport == 'docker':
self.host = self._connect_docker() self.host, self._homedir = self._connect_docker()
elif self.original_transport == 'ssh': elif self.original_transport == 'ssh':
self.host = self._connect_ssh() self.host, self._homedir = self._connect_ssh()
if self._play_context.become: if self._play_context.become:
self.context = self._connect_sudo(via=self.host) self.context, self._homedir = self._connect_sudo(via=self.host)
else: else:
self.context = self.host self.context = self.host

View File

@ -272,10 +272,19 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
Replace the base implementation's attempt to emulate Replace the base implementation's attempt to emulate
os.path.expanduser() with an actual call to os.path.expanduser(). os.path.expanduser() with an actual call to os.path.expanduser().
""" """
LOG.debug('_remove_expand_user(%r, sudoable=%r)', path, sudoable) LOG.debug('_remote_expand_user(%r, sudoable=%r)', path, sudoable)
if not path.startswith('~'):
# /home/foo -> /home/foo
return path
if path == '~':
# ~ -> /home/dmw
return self._connection.homedir
if path.startswith('~/'):
# ~/.ansible -> /home/dmw/.ansible
return os.path.join(self._connection.homedir, path[2:])
if path.startswith('~'): if path.startswith('~'):
path = self.call(os.path.expanduser, path) # ~root/.ansible -> /root/.ansible
return path return self.call(os.path.expanduser, path)
def _execute_module(self, module_name=None, module_args=None, tmp=None, def _execute_module(self, module_name=None, module_args=None, tmp=None,
task_vars=None, persist_files=False, task_vars=None, persist_files=False,

View File

@ -28,6 +28,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import logging import logging
import os.path
import zlib import zlib
import mitogen import mitogen
@ -62,7 +63,13 @@ class ContextService(mitogen.service.DeduplicatingService):
existing connection, but popped from the list of arguments passed to existing connection, but popped from the list of arguments passed to
the connection method. the connection method.
:returns mitogen.master.Context: :returns tuple:
Tuple of `(context, home_dir)`, where:
* `context` is the mitogen.master.Context referring to the target
context.
* `home_dir` is a cached copy of the remote directory.
mitogen.master.Context:
Corresponding Context instance. Corresponding Context instance.
""" """
handle = 500 handle = 500
@ -74,7 +81,9 @@ class ContextService(mitogen.service.DeduplicatingService):
def get_response(self, args): def get_response(self, args):
args.pop('discriminator', None) args.pop('discriminator', None)
method = getattr(self.router, args.pop('method')) method = getattr(self.router, args.pop('method'))
return method(**args) context = method(**args)
home_dir = context.call(os.path.expanduser, '~')
return context, home_dir
class FileService(mitogen.service.Service): class FileService(mitogen.service.Service):