Ensure remote_tmp is respected everywhere.

Logic is still somewhat different from Ansible: we don't have to care
about sudo/non-sudo cases, etc.
pull/193/head
David Wilson 7 years ago
parent 4805f3cf36
commit e0381606af

@ -177,6 +177,18 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
""" """
assert False, "_is_pipelining_enabled() should never be called." assert False, "_is_pipelining_enabled() should never be called."
def _get_remote_tmp(self):
"""
Mitogen-only: return the 'remote_tmp' setting.
"""
try:
s = self._connection._shell.get_option('remote_tmp')
except AttributeError:
# Required for <2.4.x.
s = '~/.ansible'
return self._remote_expand_user(s)
def _make_tmp_path(self, remote_user=None): def _make_tmp_path(self, remote_user=None):
""" """
Replace the base implementation's use of shell to implement mkdtemp() Replace the base implementation's use of shell to implement mkdtemp()
@ -184,18 +196,12 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
""" """
LOG.debug('_make_tmp_path(remote_user=%r)', remote_user) LOG.debug('_make_tmp_path(remote_user=%r)', remote_user)
try:
remote_tmp = self._connection._shell.get_option('remote_tmp')
except AttributeError:
# Required for <2.4.x.
remote_tmp = '~/.ansible'
# _make_tmp_path() is basically a global stashed away as Shell.tmpdir. # _make_tmp_path() is basically a global stashed away as Shell.tmpdir.
# The copy action plugin violates layering and grabs this attribute # The copy action plugin violates layering and grabs this attribute
# directly. # directly.
self._connection._shell.tmpdir = self.call( self._connection._shell.tmpdir = self.call(
ansible_mitogen.helpers.make_temp_directory, ansible_mitogen.helpers.make_temp_directory,
base_dir=self._remote_expand_user(remote_tmp), base_dir=self._get_remote_tmp(),
) )
LOG.debug('Temporary directory: %r', self._connection._shell.tmpdir) LOG.debug('Temporary directory: %r', self._connection._shell.tmpdir)
self._cleanup_remote_tmp = True self._cleanup_remote_tmp = True
@ -313,6 +319,7 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
connection=self._connection, connection=self._connection,
module_name=mitogen.utils.cast(module_name), module_name=mitogen.utils.cast(module_name),
module_args=mitogen.utils.cast(module_args), module_args=mitogen.utils.cast(module_args),
remote_tmp=mitogen.utils.cast(self._get_remote_tmp()),
task_vars=task_vars, task_vars=task_vars,
templar=self._templar, templar=self._templar,
env=mitogen.utils.cast(env), env=mitogen.utils.cast(env),

@ -92,7 +92,7 @@ class Invocation(object):
helpers.run_module() or helpers.run_module_async() in the target context. helpers.run_module() or helpers.run_module_async() in the target context.
""" """
def __init__(self, action, connection, module_name, module_args, def __init__(self, action, connection, module_name, module_args,
task_vars, templar, env, wrap_async): remote_tmp, task_vars, templar, env, wrap_async):
#: ActionBase instance invoking the module. Required to access some #: ActionBase instance invoking the module. Required to access some
#: output postprocessing methods that don't belong in ActionBase at #: output postprocessing methods that don't belong in ActionBase at
#: all. #: all.
@ -104,6 +104,9 @@ class Invocation(object):
self.module_name = module_name self.module_name = module_name
#: Final module arguments. #: Final module arguments.
self.module_args = module_args self.module_args = module_args
#: Value of 'remote_tmp' parameter, to allow target to create temporary
#: files in correct location.
self.remote_tmp = remote_tmp
#: Task variables, needed to extract ansible_*_interpreter. #: Task variables, needed to extract ansible_*_interpreter.
self.task_vars = task_vars self.task_vars = task_vars
#: Templar, needed to extract ansible_*_interpreter. #: Templar, needed to extract ansible_*_interpreter.
@ -179,6 +182,7 @@ class BinaryPlanner(Planner):
'path': invocation.module_path, 'path': invocation.module_path,
'args': invocation.module_args, 'args': invocation.module_args,
'env': invocation.env, 'env': invocation.env,
'remote_tmp': invocation.remote_tmp,
} }

@ -40,6 +40,7 @@ import cStringIO
import json import json
import logging import logging
import os import os
import shutil
import sys import sys
import tempfile import tempfile
import types import types
@ -81,16 +82,25 @@ class Runner(object):
Subclasses may override `_run`()` and extend `setup()` and `revert()`. Subclasses may override `_run`()` and extend `setup()` and `revert()`.
""" """
def __init__(self, module, raw_params=None, args=None, env=None): def __init__(self, module, remote_tmp, raw_params=None, args=None, env=None):
if args is None: if args is None:
args = {} args = {}
if raw_params is not None: if raw_params is not None:
args['_raw_params'] = raw_params args['_raw_params'] = raw_params
self.module = module self.module = module
self.remote_tmp = os.path.expanduser(remote_tmp)
self.raw_params = raw_params self.raw_params = raw_params
self.args = args self.args = args
self.env = env self.env = env
self._temp_dir = None
def get_temp_dir(self):
if not self._temp_dir:
self._temp_dir = ansible_mitogen.helpers.make_temp_directory(
self.remote_tmp,
)
return self._temp_dir
def setup(self): def setup(self):
""" """
@ -105,6 +115,8 @@ class Runner(object):
implementation simply restores the original environment. implementation simply restores the original environment.
""" """
self._env.revert() self._env.revert()
if self._temp_dir:
shutil.rmtree(self._temp_dir)
def _run(self): def _run(self):
""" """
@ -195,9 +207,9 @@ class ProgramRunner(Runner):
Create a temporary file containing the program code. The code is Create a temporary file containing the program code. The code is
fetched via :meth:`_get_program`. fetched via :meth:`_get_program`.
""" """
self.program_fp = tempfile.NamedTemporaryFile( self.program_fp = open(
prefix='ansible_mitogen', os.path.join(self.get_temp_dir(), self.module),
suffix='-binary', 'wb'
) )
self.program_fp.write(self._get_program()) self.program_fp.write(self._get_program())
self.program_fp.flush() self.program_fp.flush()
@ -224,8 +236,8 @@ class ProgramRunner(Runner):
""" """
Delete the temporary program file. Delete the temporary program file.
""" """
super(ProgramRunner, self).revert()
self.program_fp.close() self.program_fp.close()
super(ProgramRunner, self).revert()
def _run(self): def _run(self):
try: try:
@ -260,6 +272,7 @@ class ArgsFileRunner(Runner):
self.args_fp = tempfile.NamedTemporaryFile( self.args_fp = tempfile.NamedTemporaryFile(
prefix='ansible_mitogen', prefix='ansible_mitogen',
suffix='-args', suffix='-args',
dir=self.get_temp_dir(),
) )
self.args_fp.write(self._get_args_contents()) self.args_fp.write(self._get_args_contents())
self.args_fp.flush() self.args_fp.flush()
@ -282,8 +295,8 @@ class ArgsFileRunner(Runner):
""" """
Delete the temporary argument file. Delete the temporary argument file.
""" """
super(ArgsFileRunner, self).revert()
self.args_fp.close() self.args_fp.close()
super(ArgsFileRunner, self).revert()
class BinaryRunner(ArgsFileRunner, ProgramRunner): class BinaryRunner(ArgsFileRunner, ProgramRunner):

@ -161,8 +161,6 @@ Low Risk
* Only the ``sudo`` become method is available, however adding new methods is * Only the ``sudo`` become method is available, however adding new methods is
straightforward, and eventually at least ``su`` will be included. straightforward, and eventually at least ``su`` will be included.
* In some cases ``remote_tmp`` may not be respected.
* The extension's performance benefits do not scale perfectly linearly with the * The extension's performance benefits do not scale perfectly linearly with the
number of targets. This is a subject of ongoing investigation and number of targets. This is a subject of ongoing investigation and
improvements will appear in time. improvements will appear in time.

Loading…
Cancel
Save