From b4559019042ac9b4621ffb6f4e3e7debead8d1c6 Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Fri, 8 Dec 2017 06:59:24 -0800 Subject: [PATCH] Fix shebang. shebang and interpreter path weren't being templated (#33698) * Fix shebang. shebang and interpreter path weren't being templated Fixes #18665 Fixes #33696 --- lib/ansible/executor/module_common.py | 14 ++++---- lib/ansible/plugins/action/__init__.py | 9 +++-- .../module_common/test_module_common.py | 33 ++++++++++++------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py index ea8de8dbb82..1dc832ce872 100644 --- a/lib/ansible/executor/module_common.py +++ b/lib/ansible/executor/module_common.py @@ -435,7 +435,7 @@ def _slurp(path): return data -def _get_shebang(interpreter, task_vars, args=tuple()): +def _get_shebang(interpreter, task_vars, templar, args=tuple()): """ Note not stellar API: Returns None instead of always returning a shebang line. Doing it this @@ -448,7 +448,7 @@ def _get_shebang(interpreter, task_vars, args=tuple()): if interpreter_config not in task_vars: return (None, interpreter) - interpreter = task_vars[interpreter_config].strip() + interpreter = templar.template(task_vars[interpreter_config].strip()) shebang = u'#!' + interpreter if args: @@ -598,7 +598,7 @@ def _is_binary(b_module_data): return bool(start.translate(None, textchars)) -def _find_module_utils(module_name, b_module_data, module_path, module_args, task_vars, module_compression, async_timeout, become, +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, environment): """ Given the source of the module, convert it to a Jinja2 template to insert @@ -732,7 +732,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) + shebang, interpreter = _get_shebang(u'/usr/bin/python', task_vars, templar) if shebang is None: shebang = u'#!/usr/bin/python' @@ -871,7 +871,7 @@ def _find_module_utils(module_name, b_module_data, module_path, module_args, tas return (b_module_data, module_style, shebang) -def modify_module(module_name, module_path, module_args, task_vars=None, module_compression='ZIP_STORED', async_timeout=0, become=False, +def modify_module(module_name, module_path, module_args, task_vars=None, templar=None, module_compression='ZIP_STORED', async_timeout=0, become=False, become_method=None, become_user=None, become_password=None, environment=None): """ Used to insert chunks of code into modules before transfer rather than @@ -901,7 +901,7 @@ def modify_module(module_name, module_path, module_args, task_vars=None, module_ # read in the module source b_module_data = f.read() - (b_module_data, module_style, shebang) = _find_module_utils(module_name, b_module_data, module_path, module_args, task_vars, module_compression, + (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, environment=environment) @@ -916,7 +916,7 @@ def modify_module(module_name, module_path, module_args, task_vars=None, module_ interpreter = args[0] interpreter = to_bytes(interpreter) - new_shebang = to_bytes(_get_shebang(interpreter, task_vars, args[1:])[0], errors='surrogate_or_strict', nonstring='passthru') + new_shebang = to_bytes(_get_shebang(interpreter, task_vars, templar, args[1:])[0], errors='surrogate_or_strict', nonstring='passthru') if new_shebang: lines[0] = shebang = new_shebang diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index b8806baed13..5a1d3c5ffdf 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -158,9 +158,12 @@ class ActionBase(with_metaclass(ABCMeta, object)): self._compute_environment_string(final_environment) (module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, - 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, + task_vars=task_vars, templar=self._templar, + 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, environment=final_environment) diff --git a/test/units/executor/module_common/test_module_common.py b/test/units/executor/module_common/test_module_common.py index 0d7ff3e265c..69c6b30c55e 100644 --- a/test/units/executor/module_common/test_module_common.py +++ b/test/units/executor/module_common/test_module_common.py @@ -93,26 +93,35 @@ class TestSlurp(object): assert amc._slurp('some_file') == '#!/usr/bin/python\ndef test(args):\nprint("hi")\n' +@pytest.fixture +def templar(): + class FakeTemplar(object): + def template(self, template_string, *args, **kwargs): + return template_string + + return FakeTemplar() + + class TestGetShebang(object): """Note: We may want to change the API of this function in the future. It isn't a great API""" - def test_no_interpreter_set(self): - assert amc._get_shebang(u'/usr/bin/python', {}) == (None, u'/usr/bin/python') + def test_no_interpreter_set(self, templar): + assert amc._get_shebang(u'/usr/bin/python', {}, templar) == (None, u'/usr/bin/python') - def test_non_python_interpreter(self): - assert amc._get_shebang(u'/usr/bin/ruby', {}) == (None, u'/usr/bin/ruby') + def test_non_python_interpreter(self, templar): + assert amc._get_shebang(u'/usr/bin/ruby', {}, templar) == (None, u'/usr/bin/ruby') - def test_interpreter_set_in_task_vars(self): - assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/pypy'}) == \ + def test_interpreter_set_in_task_vars(self, templar): + assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/pypy'}, templar) == \ (u'#!/usr/bin/pypy', u'/usr/bin/pypy') - def test_non_python_interpreter_in_task_vars(self): - assert amc._get_shebang(u'/usr/bin/ruby', {u'ansible_ruby_interpreter': u'/usr/local/bin/ruby'}) == \ + def test_non_python_interpreter_in_task_vars(self, templar): + assert amc._get_shebang(u'/usr/bin/ruby', {u'ansible_ruby_interpreter': u'/usr/local/bin/ruby'}, templar) == \ (u'#!/usr/local/bin/ruby', u'/usr/local/bin/ruby') - def test_with_args(self): - assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/python3'}, args=('-tt', '-OO')) == \ + def test_with_args(self, templar): + assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/python3'}, templar, args=('-tt', '-OO')) == \ (u'#!/usr/bin/python3 -tt -OO', u'/usr/bin/python3') - def test_python_via_env(self): - assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/env python'}) == \ + def test_python_via_env(self, templar): + assert amc._get_shebang(u'/usr/bin/python', {u'ansible_python_interpreter': u'/usr/bin/env python'}, templar) == \ (u'#!/usr/bin/env python', u'/usr/bin/env python')