diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9a275a00c..cc803f07a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,43 +26,7 @@ jobs: include: - name: Ans_27_210 tox_env: py27-mode_ansible-ansible2.10 - - name: Ans_27_4 - tox_env: py27-mode_ansible-ansible4 - - - name: Ans_36_210 - python_version: '3.6' - tox_env: py36-mode_ansible-ansible2.10 - - name: Ans_36_4 - python_version: '3.6' - tox_env: py36-mode_ansible-ansible4 - - - name: Ans_311_210 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible2.10 - - name: Ans_311_3 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible3 - - name: Ans_311_4 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible4 - - name: Ans_311_5 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible5 - - name: Ans_313_6 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible6 - - name: Ans_313_7 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible7 - - name: Ans_313_8 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible8 - - name: Ans_313_9 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible9 - - name: Ans_313_10 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible10 + - name: Ans_313_11 python_version: '3.13' tox_env: py313-mode_ansible-ansible11 @@ -71,15 +35,6 @@ jobs: python_version: '3.13' tox_env: py313-mode_ansible-ansible11-strategy_linear - - name: Mito_27 - tox_env: py27-mode_mitogen - - name: Mito_36 - python_version: '3.6' - tox_env: py36-mode_mitogen - - name: Mito_313 - python_version: '3.13' - tox_env: py313-mode_mitogen - steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -171,12 +126,6 @@ jobs: - name: Mito_313 tox_env: py313-mode_mitogen - - name: Loc_313_11 - tox_env: py313-mode_localhost-ansible11 - - - name: Van_313_11 - tox_env: py313-mode_localhost-ansible11-strategy_linear - steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/ansible_mitogen/mixins.py b/ansible_mitogen/mixins.py index 3e995d93a..576329ce2 100644 --- a/ansible_mitogen/mixins.py +++ b/ansible_mitogen/mixins.py @@ -460,23 +460,27 @@ def _low_level_execute_command(self, cmd, sudoable=True, in_data=None, # chicken-and-egg issue, mitogen needs a python to run low_level_execute_command # which is required by Ansible's discover_interpreter function if self._mitogen_discovering_interpreter: - possible_pythons = [ - 'python3', - 'python2', - 'python' - ] + if self._connection.transport in {'ssh'}: + possible_pythons = [ + '$(for p in python3 python2 python; do command -v "$p" 2>/dev/null && break; done;)', + ] + else: + possible_pythons = ['python3' 'python2', 'python'] else: # not used, just adding a filler value possible_pythons = ['python'] for possible_python in possible_pythons: try: + LOG.debug('_low_level_execute_command(): trying %s', possible_python) self._mitogen_interpreter_candidate = possible_python rc, stdout, stderr = self._connection.exec_command( cmd, in_data, sudoable, mitogen_chdir=chdir, ) + LOG.debug('_low_level_execute_command(): got rc=%d, stdout=%r, stderr=%r', rc, stdout, stderr) # TODO: what exception is thrown? - except: + except BaseException as exc: + LOG.debug('%r._low_level_execute_command for possible_python=%r: %s, %r', self, possible_python, type(exc), exc) # we've reached the last python attempted and failed if possible_python == possible_pythons[-1]: raise diff --git a/mitogen/parent.py b/mitogen/parent.py index f301a42c5..e820bcfc3 100644 --- a/mitogen/parent.py +++ b/mitogen/parent.py @@ -1454,7 +1454,7 @@ def get_python_argv(self): return self.options.python_path return [self.options.python_path] - def get_boot_command(self): + def _first_stage_base64(self): source = inspect.getsource(self._first_stage) source = textwrap.dedent('\n'.join(source.strip().split('\n')[2:])) source = source.replace(' ', ' ') @@ -1464,17 +1464,23 @@ def get_boot_command(self): str(len(preamble_compressed))) compressed = zlib.compress(source.encode(), 9) encoded = binascii.b2a_base64(compressed).replace(b('\n'), b('')) + return encoded.decode('ascii') + def _bootstrap_argv(self): # Just enough to decode, decompress, and exec the first stage. # Priorities: wider compatibility, faster startup, shorter length. # `import os` here, instead of stage 1, to save a few bytes. # `sys.path=...` for https://github.com/python/cpython/issues/115911. - return self.get_python_argv() + [ + return [ '-c', 'import sys;sys.path=[p for p in sys.path if p];import binascii,os,zlib;' - 'exec(zlib.decompress(binascii.a2b_base64("%s")))' % (encoded.decode(),), + 'exec(zlib.decompress(binascii.a2b_base64(sys.argv[1])))', + self._first_stage_base64(), ] + def get_boot_command(self): + return self.get_python_argv() + self._bootstrap_argv() + def get_econtext_config(self): assert self.options.max_message_size is not None parent_ids = mitogen.parent_ids[:] @@ -1510,7 +1516,7 @@ def _get_name(self): def start_child(self): args = self.get_boot_command() - LOG.debug('command line for %r: %s', self, Argv(args)) + LOG.debug('command line for %r: %s', self, args) try: return self.create_child(args=args, **self.create_child_args) except OSError: diff --git a/mitogen/ssh.py b/mitogen/ssh.py index f32d2cabb..024fab158 100644 --- a/mitogen/ssh.py +++ b/mitogen/ssh.py @@ -296,10 +296,8 @@ def get_boot_command(self): if self.options.ssh_args: bits += self.options.ssh_args bits.append(self.options.hostname) - base = super(Connection, self).get_boot_command() - base_parts = [] - for s in base: - val = s if s in self.SHLEX_IGNORE else shlex_quote(s).strip() - base_parts.append(val) - return bits + base_parts + # https://datatracker.ietf.org/doc/html/rfc4254#section-6.5 + python_argv = self.get_python_argv() + bootstrap_argv = self._bootstrap_argv() + return bits + python_argv + [shlex_quote(s) for s in bootstrap_argv] diff --git a/tests/ansible/all.yml b/tests/ansible/all.yml index 7a3e70001..49a3d83a1 100644 --- a/tests/ansible/all.yml +++ b/tests/ansible/all.yml @@ -1,6 +1,4 @@ - import_playbook: setup/all.yml tags: setup -- import_playbook: regression/all.yml - tags: regression - import_playbook: integration/all.yml tags: integration