issue #477: backport ansible_mitogen.runner to 2.4.

issue510
David Wilson 5 years ago
parent 0b0ae5c971
commit 81f15028a7

@ -26,7 +26,6 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""
These classes implement execution for each style of Ansible module. They are
instantiated in the target context by way of target.py::run_module().
@ -35,14 +34,8 @@ Each class in here has a corresponding Planner class in planners.py that knows
how to build arguments for it, preseed related data, etc.
"""
from __future__ import absolute_import
from __future__ import unicode_literals
import atexit
import ctypes
import imp
import json
import logging
import os
import shlex
import shutil
@ -52,6 +45,21 @@ import types
import mitogen.core
import ansible_mitogen.target # TODO: circular import
from mitogen.core import b
from mitogen.core import bytes_partition
from mitogen.core import str_rpartition
try:
import ctypes
except ImportError:
# Python 2.4
ctypes = None
try:
import json
except ImportError:
# Python 2.4
import simplejson as json
try:
# Cannot use cStringIO as it does not support Unicode.
@ -64,6 +72,10 @@ try:
except ImportError:
from pipes import quote as shlex_quote
# Absolute imports for <2.5.
logging = __import__('logging')
# Prevent accidental import of an Ansible module from hanging on stdin read.
import ansible.module_utils.basic
ansible.module_utils.basic._ANSIBLE_ARGS = '{}'
@ -72,13 +84,14 @@ ansible.module_utils.basic._ANSIBLE_ARGS = '{}'
# resolv.conf at startup and never implicitly reload it. Cope with that via an
# explicit call to res_init() on each task invocation. BSD-alikes export it
# directly, Linux #defines it as "__res_init".
libc = ctypes.CDLL(None)
libc__res_init = None
for symbol in 'res_init', '__res_init':
try:
libc__res_init = getattr(libc, symbol)
except AttributeError:
pass
if ctypes:
libc = ctypes.CDLL(None)
for symbol in 'res_init', '__res_init':
try:
libc__res_init = getattr(libc, symbol)
except AttributeError:
pass
iteritems = getattr(dict, 'iteritems', dict.items)
LOG = logging.getLogger(__name__)
@ -118,8 +131,11 @@ class EnvironmentFileWatcher(object):
def _load(self):
try:
with open(self.path, 'r') as fp:
fp = open(self.path, 'r')
try:
return list(self._parse(fp))
finally:
fp.close()
except IOError:
return []
@ -136,7 +152,7 @@ class EnvironmentFileWatcher(object):
if bits[0] == 'export':
bits.pop(0)
key, sep, value = (' '.join(bits)).partition('=')
key, sep, value = bytes_partition(' '.join(bits), '=')
if key and sep:
yield key, value
@ -437,7 +453,7 @@ class ModuleUtilsImporter(object):
mod.__path__ = []
mod.__package__ = str(fullname)
else:
mod.__package__ = str(fullname.rpartition('.')[0])
mod.__package__ = str(str_rpartition(fullname, '.')[0])
exec(code, mod.__dict__)
self._loaded.add(fullname)
return mod
@ -581,7 +597,7 @@ class ProgramRunner(Runner):
Return the final argument vector used to execute the program.
"""
return [
self.args['_ansible_shell_executable'],
self.args.get('_ansible_shell_executable', '/bin/sh'),
'-c',
self._get_shell_fragment(),
]
@ -598,18 +614,19 @@ class ProgramRunner(Runner):
args=self._get_argv(),
emulate_tty=self.emulate_tty,
)
except Exception as e:
except Exception:
LOG.exception('While running %s', self._get_argv())
e = sys.exc_info()[1]
return {
'rc': 1,
'stdout': '',
'stderr': '%s: %s' % (type(e), e),
u'rc': 1,
u'stdout': u'',
u'stderr': u'%s: %s' % (type(e), e),
}
return {
'rc': rc,
'stdout': mitogen.core.to_text(stdout),
'stderr': mitogen.core.to_text(stderr),
u'rc': rc,
u'stdout': mitogen.core.to_text(stdout),
u'stderr': mitogen.core.to_text(stderr),
}
@ -659,7 +676,7 @@ class ScriptRunner(ProgramRunner):
self.interpreter_fragment = interpreter_fragment
self.is_python = is_python
b_ENCODING_STRING = b'# -*- coding: utf-8 -*-'
b_ENCODING_STRING = b('# -*- coding: utf-8 -*-')
def _get_program(self):
return self._rewrite_source(
@ -668,7 +685,7 @@ class ScriptRunner(ProgramRunner):
def _get_argv(self):
return [
self.args['_ansible_shell_executable'],
self.args.get('_ansible_shell_executable', '/bin/sh'),
'-c',
self._get_shell_fragment(),
]
@ -692,13 +709,13 @@ class ScriptRunner(ProgramRunner):
# While Ansible rewrites the #! using ansible_*_interpreter, it is
# never actually used to execute the script, instead it is a shell
# fragment consumed by shell/__init__.py::build_module_command().
new = [b'#!' + utf8(self.interpreter_fragment)]
new = [b('#!') + utf8(self.interpreter_fragment)]
if self.is_python:
new.append(self.b_ENCODING_STRING)
_, _, rest = s.partition(b'\n')
_, _, rest = bytes_partition(s, b('\n'))
new.append(rest)
return b'\n'.join(new)
return b('\n').join(new)
class NewStyleRunner(ScriptRunner):
@ -786,16 +803,18 @@ class NewStyleRunner(ScriptRunner):
return self._code_by_path[self.path]
except KeyError:
return self._code_by_path.setdefault(self.path, compile(
source=self.source,
filename="master:" + self.path,
mode='exec',
dont_inherit=True,
# Py2.4 doesn't support kwargs.
self.source, # source
"master:" + self.path, # filename
'exec', # mode
0, # flags
True, # dont_inherit
))
if mitogen.core.PY3:
main_module_name = '__main__'
else:
main_module_name = b'__main__'
main_module_name = b('__main__')
def _handle_magic_exception(self, mod, exc):
"""
@ -817,8 +836,8 @@ class NewStyleRunner(ScriptRunner):
exec(code, vars(mod))
else:
exec('exec code in vars(mod)')
except Exception as e:
self._handle_magic_exception(mod, e)
except Exception:
self._handle_magic_exception(mod, sys.exc_info()[1])
raise
def _run(self):
@ -834,24 +853,25 @@ class NewStyleRunner(ScriptRunner):
)
code = self._get_code()
exc = None
rc = 2
try:
try:
self._run_code(code, mod)
except SystemExit as e:
exc = e
except SystemExit:
exc = sys.exc_info()[1]
rc = exc.args[0]
finally:
self.atexit_wrapper.run_callbacks()
return {
'rc': exc.args[0] if exc else 2,
'stdout': mitogen.core.to_text(sys.stdout.getvalue()),
'stderr': mitogen.core.to_text(sys.stderr.getvalue()),
u'rc': rc,
u'stdout': mitogen.core.to_text(sys.stdout.getvalue()),
u'stderr': mitogen.core.to_text(sys.stderr.getvalue()),
}
class JsonArgsRunner(ScriptRunner):
JSON_ARGS = b'<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>'
JSON_ARGS = b('<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>')
def _get_args_contents(self):
return json.dumps(self.args).encode()

Loading…
Cancel
Save