diff options
author | Brian Coca <bcoca@users.noreply.github.com> | 2021-08-04 11:41:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-04 11:41:58 -0400 |
commit | 8d41b97329cae281ce194dbb8cb3ce35fdce23ec (patch) | |
tree | a15c9d61b0b6ae0f902f8fe85fbd1521d667a356 /lib/ansible | |
parent | 1d2af0b89ecc0fd7e2a97112a0916b287ebfa9e8 (diff) | |
download | ansible-8d41b97329cae281ce194dbb8cb3ce35fdce23ec.tar.gz |
Skip python interpreter discovery for 'forced local' module execution (#74824)
mostly for use with network_os
use 'remote is local' property as indicator
ensure task_vars are as expected in test
Diffstat (limited to 'lib/ansible')
-rw-r--r-- | lib/ansible/executor/module_common.py | 83 | ||||
-rw-r--r-- | lib/ansible/plugins/action/__init__.py | 1 |
2 files changed, 50 insertions, 34 deletions
diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py index f121af8085..b58aeba0cf 100644 --- a/lib/ansible/executor/module_common.py +++ b/lib/ansible/executor/module_common.py @@ -587,7 +587,7 @@ def _slurp(path): return data -def _get_shebang(interpreter, task_vars, templar, args=tuple()): +def _get_shebang(interpreter, task_vars, templar, args=tuple(), remote_is_local=False): """ Note not stellar API: Returns None instead of always returning a shebang line. Doing it this @@ -595,44 +595,59 @@ def _get_shebang(interpreter, task_vars, templar, args=tuple()): file rather than trust that we reformatted what they already have correctly. """ - interpreter_name = os.path.basename(interpreter).strip() - # FUTURE: add logical equivalence for python3 in the case of py3-only modules - # check for first-class interpreter config - interpreter_config_key = "INTERPRETER_%s" % interpreter_name.upper() + interpreter_name = os.path.basename(interpreter).strip() - if C.config.get_configuration_definitions().get(interpreter_config_key): - # a config def exists for this interpreter type; consult config for the value - interpreter_out = C.config.get_config_value(interpreter_config_key, variables=task_vars) - discovered_interpreter_config = u'discovered_interpreter_%s' % interpreter_name + # name for interpreter var + interpreter_config = u'ansible_%s_interpreter' % interpreter_name + # key for config + interpreter_config_key = "INTERPRETER_%s" % interpreter_name.upper() - interpreter_out = templar.template(interpreter_out.strip()) + interpreter_out = None - facts_from_task_vars = task_vars.get('ansible_facts', {}) + # looking for python, rest rely on matching vars + if interpreter_name == 'python': + # skip detection for network os execution, use playbook supplied one if possible + if remote_is_local: + interpreter_out = task_vars['ansible_playbook_python'] - # handle interpreter discovery if requested - if interpreter_out in ['auto', 'auto_legacy', 'auto_silent', 'auto_legacy_silent']: - if discovered_interpreter_config not in facts_from_task_vars: - # interpreter discovery is desired, but has not been run for this host - raise InterpreterDiscoveryRequiredError("interpreter discovery needed", - interpreter_name=interpreter_name, - discovery_mode=interpreter_out) - else: - interpreter_out = facts_from_task_vars[discovered_interpreter_config] - else: - # a config def does not exist for this interpreter type; consult vars for a possible direct override - interpreter_config = u'ansible_%s_interpreter' % interpreter_name + # a config def exists for this interpreter type; consult config for the value + elif C.config.get_configuration_definition(interpreter_config_key): - if interpreter_config not in task_vars: - return None, interpreter + interpreter_from_config = C.config.get_config_value(interpreter_config_key, variables=task_vars) + interpreter_out = templar.template(interpreter_from_config.strip()) - interpreter_out = templar.template(task_vars[interpreter_config].strip()) + # handle interpreter discovery if requested or empty interpreter was provided + if not interpreter_out or interpreter_out in ['auto', 'auto_legacy', 'auto_silent', 'auto_legacy_silent']: - shebang = u'#!' + interpreter_out + discovered_interpreter_config = u'discovered_interpreter_%s' % interpreter_name + facts_from_task_vars = task_vars.get('ansible_facts', {}) - if args: - shebang = shebang + u' ' + u' '.join(args) + if discovered_interpreter_config not in facts_from_task_vars: + # interpreter discovery is desired, but has not been run for this host + raise InterpreterDiscoveryRequiredError("interpreter discovery needed", interpreter_name=interpreter_name, discovery_mode=interpreter_out) + else: + interpreter_out = facts_from_task_vars[discovered_interpreter_config] + else: + raise InterpreterDiscoveryRequiredError("interpreter discovery required", interpreter_name=interpreter_name, discovery_mode='auto_legacy') + + elif interpreter_config in task_vars: + # for non python we consult vars for a possible direct override + interpreter_out = templar.template(task_vars.get(interpreter_config).strip()) + + if not interpreter_out: + # nothing matched(None) or in case someone configures empty string or empty intepreter + interpreter_out = interpreter + shebang = None + elif interpreter_out == interpreter: + # no change, no new shebang + shebang = None + else: + # set shebang cause we changed interpreter + shebang = u'#!' + interpreter_out + if args: + shebang = shebang + u' ' + u' '.join(args) return shebang, interpreter_out @@ -1067,7 +1082,7 @@ def _add_module_to_zip(zf, remote_module_fqn, b_module_data): def _find_module_utils(module_name, b_module_data, module_path, module_args, task_vars, templar, module_compression, async_timeout, become, - become_method, become_user, become_password, become_flags, environment): + become_method, become_user, become_password, become_flags, environment, remote_is_local=False): """ Given the source of the module, convert it to a Jinja2 template to insert module code and return whether it's a new or old style module. @@ -1221,7 +1236,7 @@ def _find_module_utils(module_name, b_module_data, module_path, module_args, tas 'Look at traceback for that process for debugging information.') zipdata = to_text(zipdata, errors='surrogate_or_strict') - shebang, interpreter = _get_shebang(u'/usr/bin/python', task_vars, templar) + shebang, interpreter = _get_shebang(u'/usr/bin/python', task_vars, templar, remote_is_local=remote_is_local) if shebang is None: shebang = u'#!/usr/bin/python' @@ -1313,7 +1328,7 @@ def _find_module_utils(module_name, b_module_data, module_path, module_args, tas def modify_module(module_name, module_path, module_args, templar, task_vars=None, module_compression='ZIP_STORED', async_timeout=0, become=False, - become_method=None, become_user=None, become_password=None, become_flags=None, environment=None): + become_method=None, become_user=None, become_password=None, become_flags=None, environment=None, remote_is_local=False): """ Used to insert chunks of code into modules before transfer rather than doing regular python imports. This allows for more efficient transfer in @@ -1345,7 +1360,7 @@ def modify_module(module_name, module_path, module_args, templar, task_vars=None (b_module_data, module_style, shebang) = _find_module_utils(module_name, b_module_data, module_path, module_args, task_vars, templar, module_compression, async_timeout=async_timeout, become=become, become_method=become_method, become_user=become_user, become_password=become_password, become_flags=become_flags, - environment=environment) + environment=environment, remote_is_local=remote_is_local) if module_style == 'binary': return (b_module_data, module_style, to_text(shebang, nonstring='passthru')) @@ -1359,7 +1374,7 @@ def modify_module(module_name, module_path, module_args, templar, task_vars=None # _get_shebang() takes text strings args = [to_text(a, errors='surrogate_or_strict') for a in args] interpreter = args[0] - b_new_shebang = to_bytes(_get_shebang(interpreter, task_vars, templar, args[1:])[0], + b_new_shebang = to_bytes(_get_shebang(interpreter, task_vars, templar, args[1:], remote_is_local=remote_is_local)[0], errors='surrogate_or_strict', nonstring='passthru') if b_new_shebang: diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index 68b949534b..c071157b74 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -234,6 +234,7 @@ class ActionBase(with_metaclass(ABCMeta, object)): module_compression=self._play_context.module_compression, async_timeout=self._task.async_val, environment=final_environment, + remote_is_local=bool(getattr(self._connection, '_remote_is_local', False)), **become_kwargs) break except InterpreterDiscoveryRequiredError as idre: |