mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-27 19:39:13 -07:00
Python interpreter discovery (#50163)
* Python interpreter discovery * No longer blindly default to only `/usr/bin/python` * `ansible_python_interpreter` defaults to `auto_legacy`, which will discover the platform Python interpreter on some platforms (but still favor `/usr/bin/python` if present for backward compatibility). Use `auto` to always use the discovered interpreter, append `_silent` to either value to suppress warnings. * includes new doc utility method `get_versioned_doclink` to generate a major.minor versioned doclink against docs.ansible.com (or some other config-overridden URL) * docs revisions for python interpreter discovery (cherry picked from commit 5b53c0012ab7212304c28fdd24cb33fd8ff755c2) * verify output on some distros, cleanup
This commit is contained in:
parent
b8a82f5930
commit
4d3a6123d5
20 changed files with 759 additions and 28 deletions
|
@ -20,6 +20,7 @@ from abc import ABCMeta, abstractmethod
|
|||
from ansible import constants as C
|
||||
from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleActionSkip, AnsibleActionFail
|
||||
from ansible.executor.module_common import modify_module
|
||||
from ansible.executor.interpreter_discovery import discover_interpreter, InterpreterDiscoveryRequiredError
|
||||
from ansible.module_utils.json_utils import _filter_non_json_lines
|
||||
from ansible.module_utils.six import binary_type, string_types, text_type, iteritems, with_metaclass
|
||||
from ansible.module_utils.six.moves import shlex_quote
|
||||
|
@ -30,7 +31,6 @@ from ansible.utils.display import Display
|
|||
from ansible.utils.unsafe_proxy import wrap_var
|
||||
from ansible.vars.clean import remove_internal_keys
|
||||
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
|
@ -58,6 +58,12 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|||
self._supports_check_mode = True
|
||||
self._supports_async = False
|
||||
|
||||
# interpreter discovery state
|
||||
self._discovered_interpreter_key = None
|
||||
self._discovered_interpreter = False
|
||||
self._discovery_deprecation_warnings = []
|
||||
self._discovery_warnings = []
|
||||
|
||||
# Backwards compat: self._display isn't really needed, just import the global display and use that.
|
||||
self._display = display
|
||||
|
||||
|
@ -181,16 +187,36 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|||
final_environment = dict()
|
||||
self._compute_environment_string(final_environment)
|
||||
|
||||
(module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, self._templar,
|
||||
task_vars=task_vars,
|
||||
module_compression=self._play_context.module_compression,
|
||||
async_timeout=self._task.async_val,
|
||||
become=self._play_context.become,
|
||||
become_method=self._play_context.become_method,
|
||||
become_user=self._play_context.become_user,
|
||||
become_password=self._play_context.become_pass,
|
||||
become_flags=self._play_context.become_flags,
|
||||
environment=final_environment)
|
||||
# modify_module will exit early if interpreter discovery is required; re-run after if necessary
|
||||
for dummy in (1, 2):
|
||||
try:
|
||||
(module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, self._templar,
|
||||
task_vars=task_vars,
|
||||
module_compression=self._play_context.module_compression,
|
||||
async_timeout=self._task.async_val,
|
||||
become=self._play_context.become,
|
||||
become_method=self._play_context.become_method,
|
||||
become_user=self._play_context.become_user,
|
||||
become_password=self._play_context.become_pass,
|
||||
become_flags=self._play_context.become_flags,
|
||||
environment=final_environment)
|
||||
break
|
||||
except InterpreterDiscoveryRequiredError as idre:
|
||||
self._discovered_interpreter = discover_interpreter(
|
||||
action=self,
|
||||
interpreter_name=idre.interpreter_name,
|
||||
discovery_mode=idre.discovery_mode,
|
||||
task_vars=task_vars)
|
||||
|
||||
# update the local task_vars with the discovered interpreter (which might be None);
|
||||
# we'll propagate back to the controller in the task result
|
||||
discovered_key = 'discovered_interpreter_%s' % idre.interpreter_name
|
||||
# store in local task_vars facts collection for the retry and any other usages in this worker
|
||||
if task_vars.get('ansible_facts') is None:
|
||||
task_vars['ansible_facts'] = {}
|
||||
task_vars['ansible_facts'][discovered_key] = self._discovered_interpreter
|
||||
# preserve this so _execute_module can propagate back to controller as a fact
|
||||
self._discovered_interpreter_key = discovered_key
|
||||
|
||||
return (module_style, module_shebang, module_data, module_path)
|
||||
|
||||
|
@ -904,6 +930,23 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|||
txt = data.get('stderr', None) or u''
|
||||
data['stderr_lines'] = txt.splitlines()
|
||||
|
||||
# propagate interpreter discovery results back to the controller
|
||||
if self._discovered_interpreter_key:
|
||||
if data.get('ansible_facts') is None:
|
||||
data['ansible_facts'] = {}
|
||||
|
||||
data['ansible_facts'][self._discovered_interpreter_key] = self._discovered_interpreter
|
||||
|
||||
if self._discovery_warnings:
|
||||
if data.get('warnings') is None:
|
||||
data['warnings'] = []
|
||||
data['warnings'].extend(self._discovery_warnings)
|
||||
|
||||
if self._discovery_deprecation_warnings:
|
||||
if data.get('deprecations') is None:
|
||||
data['deprecations'] = []
|
||||
data['deprecations'].extend(self._discovery_deprecation_warnings)
|
||||
|
||||
display.debug("done with _execute_module (%s, %s)" % (module_name, module_args))
|
||||
return data
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue