able to pass tests running interpreter detection in rhel8 container

This commit is contained in:
Steven Robertson 2020-03-03 22:03:49 -08:00
parent 7d6d76e444
commit 89d87445c8
2 changed files with 57 additions and 8 deletions

View File

@ -122,6 +122,7 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
# required for python interpreter discovery
connection.templar = self._templar
self._finding_python_interpreter = False
self._rediscovered_python = False
# redeclaring interpreter discovery vars here in case running ansible < 2.8.0
self._discovered_interpreter_key = None
self._discovered_interpreter = False
@ -402,7 +403,11 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
if result.get('ansible_facts') is None:
result['ansible_facts'] = {}
result['ansible_facts'][self._discovered_interpreter_key] = self._discovered_interpreter
# only cache discovered_interpreter if we're not running a rediscovery
# rediscovery happens in places like docker connections that could have different
# python interpreters than the main host
if not self._rediscovered_python:
result['ansible_facts'][self._discovered_interpreter_key] = self._discovered_interpreter
if self._discovery_warnings:
if result.get('warnings') is None:
@ -457,12 +462,47 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
if executable:
cmd = executable + ' -c ' + shlex_quote(cmd)
rc, stdout, stderr = self._connection.exec_command(
cmd=cmd,
in_data=in_data,
sudoable=sudoable,
mitogen_chdir=chdir,
)
# TODO: HACK: if finding python interpreter then we need to keep
# calling exec_command until we run into the right python we'll use
# 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._finding_python_interpreter:
possible_pythons = [
'/usr/bin/python',
'python3.7',
'python3.6',
'python3.5',
'python2.7',
'python2.6',
'usr/libexec/platform-python',
'usr/bin/python3',
'python'
]
else:
# not used, just adding a filler value
possible_pythons = ['python']
def _run_cmd():
return self._connection.exec_command(
cmd=cmd,
in_data=in_data,
sudoable=sudoable,
mitogen_chdir=chdir,
)
for possible_python in possible_pythons:
try:
self._possible_python_interpreter = possible_python
rc, stdout, stderr = _run_cmd()
# TODO: what exception is thrown?
except:
# we've reached the last python attempted and failed
# TODO: could use enumerate(), need to check which version of python first had it though
if possible_python == 'python':
raise
else:
continue
stdout_text = to_text(stdout, errors=encoding_errors)
return {

View File

@ -88,7 +88,10 @@ def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_pyth
For connections like `docker`, we want to rediscover the python interpreter because
it could be different than what's ran on the host
"""
# TODO: avoid infinite recursion via _finding_python_interpreter + low_level_execute_command called from discover_interpreter
# keep trying different interpreters until we don't error
if action._finding_python_interpreter:
return action._possible_python_interpreter
if s in ['auto', 'auto_legacy', 'auto_silent', 'auto_legacy_silent']:
# python is the only supported interpreter_name as of Ansible 2.8.8
interpreter_name = 'python'
@ -98,6 +101,11 @@ def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_pyth
task_vars['ansible_facts'] = {}
if rediscover_python and task_vars.get('ansible_facts', {}).get(discovered_interpreter_config):
# if we're rediscovering python then chances are we're running something like a docker connection
# this will handle scenarios like running a playbook that does stuff + then dynamically creates a docker container,
# then runs the rest of the playbook inside that container, and then rerunning the playbook again
action._rediscovered_python = True
# blow away the discovered_interpreter_config cache and rediscover
del task_vars['ansible_facts'][discovered_interpreter_config]
@ -110,6 +118,7 @@ def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_pyth
interpreter_name=interpreter_name,
discovery_mode=s,
task_vars=task_vars))
# cache discovered interpreter
task_vars['ansible_facts'][discovered_interpreter_config] = s
action._connection.has_pipelining = False