Skip to content

Commit 1596813

Browse files
committed
WIP
1 parent 837111c commit 1596813

File tree

4 files changed

+36
-31
lines changed

4 files changed

+36
-31
lines changed

ansible_mitogen/mixins.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -465,30 +465,27 @@ def _low_level_execute_command(self, cmd, sudoable=True, in_data=None,
465465
# chicken-and-egg issue, mitogen needs a python to run low_level_execute_command
466466
# which is required by Ansible's discover_interpreter function
467467
if self._mitogen_discovering_interpreter:
468-
possible_pythons = [
469-
'/usr/bin/python',
470-
'python3',
471-
'python3.7',
472-
'python3.6',
473-
'python3.5',
474-
'python2.7',
475-
'python2.6',
476-
'/usr/libexec/platform-python',
477-
'/usr/bin/python3',
478-
'python'
479-
]
468+
if self._connection.transport in {'ssh'}:
469+
possible_pythons = [
470+
'$(for p in python3 python2 python; do command -v "$p" 2>/dev/null && break; done;)',
471+
]
472+
else:
473+
possible_pythons = ['python3' 'python2', 'python']
480474
else:
481475
# not used, just adding a filler value
482476
possible_pythons = ['python']
483477

484478
for possible_python in possible_pythons:
485479
try:
480+
LOG.debug('_low_level_execute_command(): trying possible_python=%r', possible_python)
486481
self._mitogen_interpreter_candidate = possible_python
487482
rc, stdout, stderr = self._connection.exec_command(
488483
cmd, in_data, sudoable, mitogen_chdir=chdir,
489484
)
485+
LOG.debug('_low_level_execute_command(): got rc=%d, stdout=%r, stderr=%r', rc, stdout, stderr)
490486
# TODO: what exception is thrown?
491-
except:
487+
except BaseException as exc:
488+
LOG.debug('%r._low_level_execute_command for possible_python=%r: %s, %r', self, possible_python, type(exc), exc)
492489
# we've reached the last python attempted and failed
493490
if possible_python == possible_pythons[-1]:
494491
raise

ansible_mitogen/transport_config.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,19 @@
7373
from ansible.module_utils.six import with_metaclass
7474
from ansible.module_utils.parsing.convert_bool import boolean
7575

76+
import ansible_mitogen.utils
7677
import mitogen.core
7778

7879

7980
LOG = logging.getLogger(__name__)
8081

82+
if ansible_mitogen.utils.ansible_version[:2] >= (2, 19):
83+
_FALLBACK_INTERPRETER = ansible.executor.interpreter_discovery._FALLBACK_INTERPRETER
84+
elif ansible_mitogen.utils.ansible_version[:2] >= (2, 17):
85+
_FALLBACK_INTERPRETER = u'/usr/bin/python3'
86+
else:
87+
_FALLBACK_INTERPRETER = u'/usr/bin/python'
88+
8189

8290
def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_python):
8391
"""
@@ -107,7 +115,9 @@ def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_pyth
107115
# blow away the discovered_interpreter_config cache and rediscover
108116
del task_vars['ansible_facts'][discovered_interpreter_config]
109117

110-
if discovered_interpreter_config not in task_vars['ansible_facts']:
118+
try:
119+
s = task_vars['ansible_facts'][discovered_interpreter_config]
120+
except KeyError:
111121
action._mitogen_discovering_interpreter = True
112122
# fake pipelining so discover_interpreter can be happy
113123
action._connection.has_pipelining = True
@@ -121,8 +131,6 @@ def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_pyth
121131
# cache discovered interpreter
122132
task_vars['ansible_facts'][discovered_interpreter_config] = s
123133
action._connection.has_pipelining = False
124-
else:
125-
s = task_vars['ansible_facts'][discovered_interpreter_config]
126134

127135
# propagate discovered interpreter as fact
128136
action._discovered_interpreter_key = discovered_interpreter_config
@@ -144,9 +152,8 @@ def parse_python_path(s, task_vars, action, rediscover_python):
144152
s = 'auto'
145153

146154
s = run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_python)
147-
# if unable to determine python_path, fallback to '/usr/bin/python'
148155
if not s:
149-
s = '/usr/bin/python'
156+
raise ValueError("Interpreter discovery failed, got: %r", s)
150157

151158
return ansible.utils.shlex.shlex_split(s)
152159

@@ -715,9 +722,6 @@ def port(self):
715722

716723
def python_path(self, rediscover_python=False):
717724
s = self._host_vars.get('ansible_python_interpreter')
718-
# #511, #536: executor/module_common.py::_get_shebang() hard-wires
719-
# "/usr/bin/python" as the default interpreter path if no other
720-
# interpreter is specified.
721725
return parse_python_path(
722726
s,
723727
task_vars=self._task_vars,

mitogen/parent.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,7 +1462,7 @@ def get_python_argv(self):
14621462
return self.options.python_path
14631463
return [self.options.python_path]
14641464

1465-
def get_boot_command(self):
1465+
def _first_stage_base64(self):
14661466
source = inspect.getsource(self._first_stage)
14671467
source = textwrap.dedent('\n'.join(source.strip().split('\n')[2:]))
14681468
source = source.replace(' ', ' ')
@@ -1472,17 +1472,23 @@ def get_boot_command(self):
14721472
str(len(preamble_compressed)))
14731473
compressed = zlib.compress(source.encode(), 9)
14741474
encoded = binascii.b2a_base64(compressed).replace(b('\n'), b(''))
1475+
return encoded.decode('ascii')
14751476

1477+
def _bootstrap_argv(self):
14761478
# Just enough to decode, decompress, and exec the first stage.
14771479
# Priorities: wider compatibility, faster startup, shorter length.
14781480
# `import os` here, instead of stage 1, to save a few bytes.
14791481
# `sys.path=...` for https://github.com/python/cpython/issues/115911.
1480-
return self.get_python_argv() + [
1482+
return [
14811483
'-c',
14821484
'import sys;sys.path=[p for p in sys.path if p];import binascii,os,zlib;'
1483-
'exec(zlib.decompress(binascii.a2b_base64("%s")))' % (encoded.decode(),),
1485+
'exec(zlib.decompress(binascii.a2b_base64(sys.argv[1])))',
1486+
self._first_stage_base64(),
14841487
]
14851488

1489+
def get_boot_command(self):
1490+
return self.get_python_argv() + self._bootstrap_argv()
1491+
14861492
def get_econtext_config(self):
14871493
assert self.options.max_message_size is not None
14881494
parent_ids = mitogen.parent_ids[:]
@@ -1518,7 +1524,7 @@ def _get_name(self):
15181524

15191525
def start_child(self):
15201526
args = self.get_boot_command()
1521-
LOG.debug('command line for %r: %s', self, Argv(args))
1527+
LOG.debug('command line for %r: %s', self, args)
15221528
try:
15231529
return self.create_child(args=args, **self.create_child_args)
15241530
except OSError:

mitogen/ssh.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,8 @@ def get_boot_command(self):
296296
if self.options.ssh_args:
297297
bits += self.options.ssh_args
298298
bits.append(self.options.hostname)
299-
base = super(Connection, self).get_boot_command()
300299

301-
base_parts = []
302-
for s in base:
303-
val = s if s in self.SHLEX_IGNORE else shlex_quote(s).strip()
304-
base_parts.append(val)
305-
return bits + base_parts
300+
# https://datatracker.ietf.org/doc/html/rfc4254#section-6.5
301+
python_argv = self.get_python_argv()
302+
bootstrap_argv = self._bootstrap_argv()
303+
return bits + python_argv + [shlex_quote(s) for s in bootstrap_argv]

0 commit comments

Comments
 (0)