|
|
@ -40,7 +40,10 @@ from __future__ import absolute_import, division, print_function
|
|
|
|
__metaclass__ = type
|
|
|
|
__metaclass__ = type
|
|
|
|
|
|
|
|
|
|
|
|
import atexit
|
|
|
|
import atexit
|
|
|
|
|
|
|
|
import ctypes
|
|
|
|
import json
|
|
|
|
import json
|
|
|
|
|
|
|
|
import io
|
|
|
|
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import re
|
|
|
|
import shlex
|
|
|
|
import shlex
|
|
|
@ -50,19 +53,12 @@ import tempfile
|
|
|
|
import traceback
|
|
|
|
import traceback
|
|
|
|
import types
|
|
|
|
import types
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from ansible.module_utils.six.moves import iteritems, shlex_quote
|
|
|
|
|
|
|
|
|
|
|
|
import mitogen.core
|
|
|
|
import mitogen.core
|
|
|
|
import ansible_mitogen.target # TODO: circular import
|
|
|
|
import ansible_mitogen.target # TODO: circular import
|
|
|
|
from mitogen.core import b
|
|
|
|
|
|
|
|
from mitogen.core import bytes_partition
|
|
|
|
|
|
|
|
from mitogen.core import str_rpartition
|
|
|
|
|
|
|
|
from mitogen.core import to_text
|
|
|
|
from mitogen.core import to_text
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
import ctypes
|
|
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
|
|
# Python 2.4
|
|
|
|
|
|
|
|
ctypes = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
# Python >= 3.4, PEP 451 ModuleSpec API
|
|
|
|
# Python >= 3.4, PEP 451 ModuleSpec API
|
|
|
|
import importlib.machinery
|
|
|
|
import importlib.machinery
|
|
|
@ -71,21 +67,6 @@ except ImportError:
|
|
|
|
# Python < 3.4, PEP 302 Import Hooks
|
|
|
|
# Python < 3.4, PEP 302 Import Hooks
|
|
|
|
import imp
|
|
|
|
import imp
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
# Cannot use cStringIO as it does not support Unicode.
|
|
|
|
|
|
|
|
from StringIO import StringIO
|
|
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
|
|
from io import StringIO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
from shlex import quote as shlex_quote
|
|
|
|
|
|
|
|
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.
|
|
|
|
# Prevent accidental import of an Ansible module from hanging on stdin read.
|
|
|
|
import ansible.module_utils.basic
|
|
|
|
import ansible.module_utils.basic
|
|
|
|
ansible.module_utils.basic._ANSIBLE_ARGS = '{}'
|
|
|
|
ansible.module_utils.basic._ANSIBLE_ARGS = '{}'
|
|
|
@ -103,7 +84,6 @@ if ctypes:
|
|
|
|
except AttributeError:
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
iteritems = getattr(dict, 'iteritems', dict.items)
|
|
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -217,13 +197,13 @@ class EnvironmentFileWatcher(object):
|
|
|
|
for line in fp:
|
|
|
|
for line in fp:
|
|
|
|
# ' #export foo=some var ' -> ['#export', 'foo=some var ']
|
|
|
|
# ' #export foo=some var ' -> ['#export', 'foo=some var ']
|
|
|
|
bits = shlex_split_b(line)
|
|
|
|
bits = shlex_split_b(line)
|
|
|
|
if (not bits) or bits[0].startswith(b('#')):
|
|
|
|
if (not bits) or bits[0].startswith(b'#'):
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
if bits[0] == b('export'):
|
|
|
|
if bits[0] == b'export':
|
|
|
|
bits.pop(0)
|
|
|
|
bits.pop(0)
|
|
|
|
|
|
|
|
|
|
|
|
key, sep, value = bytes_partition(b(' ').join(bits), b('='))
|
|
|
|
key, sep, value = b' '.join(bits).partition(b'=')
|
|
|
|
if key and sep:
|
|
|
|
if key and sep:
|
|
|
|
yield key, value
|
|
|
|
yield key, value
|
|
|
|
|
|
|
|
|
|
|
@ -596,7 +576,7 @@ class ModuleUtilsImporter(object):
|
|
|
|
mod.__path__ = []
|
|
|
|
mod.__path__ = []
|
|
|
|
mod.__package__ = str(fullname)
|
|
|
|
mod.__package__ = str(fullname)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
mod.__package__ = str(str_rpartition(to_text(fullname), '.')[0])
|
|
|
|
mod.__package__ = str(to_text(fullname).rpartition('.')[0])
|
|
|
|
exec(code, mod.__dict__)
|
|
|
|
exec(code, mod.__dict__)
|
|
|
|
self._loaded.add(fullname)
|
|
|
|
self._loaded.add(fullname)
|
|
|
|
return mod
|
|
|
|
return mod
|
|
|
@ -647,11 +627,11 @@ class NewStyleStdio(object):
|
|
|
|
self.original_stdout = sys.stdout
|
|
|
|
self.original_stdout = sys.stdout
|
|
|
|
self.original_stderr = sys.stderr
|
|
|
|
self.original_stderr = sys.stderr
|
|
|
|
self.original_stdin = sys.stdin
|
|
|
|
self.original_stdin = sys.stdin
|
|
|
|
sys.stdout = StringIO()
|
|
|
|
sys.stdout = io.StringIO()
|
|
|
|
sys.stderr = StringIO()
|
|
|
|
sys.stderr = io.StringIO()
|
|
|
|
encoded = json.dumps({'ANSIBLE_MODULE_ARGS': args})
|
|
|
|
encoded = json.dumps({'ANSIBLE_MODULE_ARGS': args})
|
|
|
|
ansible.module_utils.basic._ANSIBLE_ARGS = utf8(encoded)
|
|
|
|
ansible.module_utils.basic._ANSIBLE_ARGS = utf8(encoded)
|
|
|
|
sys.stdin = StringIO(mitogen.core.to_text(encoded))
|
|
|
|
sys.stdin = io.StringIO(mitogen.core.to_text(encoded))
|
|
|
|
|
|
|
|
|
|
|
|
self.original_get_path = getattr(ansible.module_utils.basic,
|
|
|
|
self.original_get_path = getattr(ansible.module_utils.basic,
|
|
|
|
'get_module_path', None)
|
|
|
|
'get_module_path', None)
|
|
|
@ -819,7 +799,7 @@ class ScriptRunner(ProgramRunner):
|
|
|
|
self.interpreter_fragment = interpreter_fragment
|
|
|
|
self.interpreter_fragment = interpreter_fragment
|
|
|
|
self.is_python = is_python
|
|
|
|
self.is_python = is_python
|
|
|
|
|
|
|
|
|
|
|
|
b_ENCODING_STRING = b('# -*- coding: utf-8 -*-')
|
|
|
|
b_ENCODING_STRING = b'# -*- coding: utf-8 -*-'
|
|
|
|
|
|
|
|
|
|
|
|
def _get_program(self):
|
|
|
|
def _get_program(self):
|
|
|
|
return self._rewrite_source(
|
|
|
|
return self._rewrite_source(
|
|
|
@ -852,13 +832,13 @@ class ScriptRunner(ProgramRunner):
|
|
|
|
# While Ansible rewrites the #! using ansible_*_interpreter, it is
|
|
|
|
# While Ansible rewrites the #! using ansible_*_interpreter, it is
|
|
|
|
# never actually used to execute the script, instead it is a shell
|
|
|
|
# never actually used to execute the script, instead it is a shell
|
|
|
|
# fragment consumed by shell/__init__.py::build_module_command().
|
|
|
|
# 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:
|
|
|
|
if self.is_python:
|
|
|
|
new.append(self.b_ENCODING_STRING)
|
|
|
|
new.append(self.b_ENCODING_STRING)
|
|
|
|
|
|
|
|
|
|
|
|
_, _, rest = bytes_partition(s, b('\n'))
|
|
|
|
_, _, rest = s.partition(b'\n')
|
|
|
|
new.append(rest)
|
|
|
|
new.append(rest)
|
|
|
|
return b('\n').join(new)
|
|
|
|
return b'\n'.join(new)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NewStyleRunner(ScriptRunner):
|
|
|
|
class NewStyleRunner(ScriptRunner):
|
|
|
@ -971,8 +951,7 @@ class NewStyleRunner(ScriptRunner):
|
|
|
|
# change the default encoding. This hack was removed from Ansible long ago,
|
|
|
|
# change the default encoding. This hack was removed from Ansible long ago,
|
|
|
|
# but not before permeating into many third party modules.
|
|
|
|
# but not before permeating into many third party modules.
|
|
|
|
PREHISTORIC_HACK_RE = re.compile(
|
|
|
|
PREHISTORIC_HACK_RE = re.compile(
|
|
|
|
b(r'reload\s*\(\s*sys\s*\)\s*'
|
|
|
|
rb'reload\s*\(\s*sys\s*\)\s*sys\s*\.\s*setdefaultencoding\([^)]+\)',
|
|
|
|
r'sys\s*\.\s*setdefaultencoding\([^)]+\)')
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def _setup_program(self):
|
|
|
|
def _setup_program(self):
|
|
|
@ -980,7 +959,7 @@ class NewStyleRunner(ScriptRunner):
|
|
|
|
context=self.service_context,
|
|
|
|
context=self.service_context,
|
|
|
|
path=self.path,
|
|
|
|
path=self.path,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.source = self.PREHISTORIC_HACK_RE.sub(b(''), source)
|
|
|
|
self.source = self.PREHISTORIC_HACK_RE.sub(b'', source)
|
|
|
|
|
|
|
|
|
|
|
|
def _get_code(self):
|
|
|
|
def _get_code(self):
|
|
|
|
try:
|
|
|
|
try:
|
|
|
@ -998,7 +977,7 @@ class NewStyleRunner(ScriptRunner):
|
|
|
|
if mitogen.core.PY3:
|
|
|
|
if mitogen.core.PY3:
|
|
|
|
main_module_name = '__main__'
|
|
|
|
main_module_name = '__main__'
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
main_module_name = b('__main__')
|
|
|
|
main_module_name = b'__main__'
|
|
|
|
|
|
|
|
|
|
|
|
def _handle_magic_exception(self, mod, exc):
|
|
|
|
def _handle_magic_exception(self, mod, exc):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
@ -1030,7 +1009,7 @@ class NewStyleRunner(ScriptRunner):
|
|
|
|
approximation of the original package hierarchy, so that relative
|
|
|
|
approximation of the original package hierarchy, so that relative
|
|
|
|
imports function correctly.
|
|
|
|
imports function correctly.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
pkg, sep, modname = str_rpartition(self.py_module_name, '.')
|
|
|
|
pkg, sep, _ = self.py_module_name.rpartition('.')
|
|
|
|
if not sep:
|
|
|
|
if not sep:
|
|
|
|
return None
|
|
|
|
return None
|
|
|
|
if mitogen.core.PY3:
|
|
|
|
if mitogen.core.PY3:
|
|
|
@ -1073,7 +1052,7 @@ class NewStyleRunner(ScriptRunner):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class JsonArgsRunner(ScriptRunner):
|
|
|
|
class JsonArgsRunner(ScriptRunner):
|
|
|
|
JSON_ARGS = b('<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>')
|
|
|
|
JSON_ARGS = b'<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>'
|
|
|
|
|
|
|
|
|
|
|
|
def _get_args_contents(self):
|
|
|
|
def _get_args_contents(self):
|
|
|
|
return json.dumps(self.args).encode()
|
|
|
|
return json.dumps(self.args).encode()
|
|
|
|