Complete rewrite of Windows exec wrapper (#21510)

* supports pipelining for faster execution
* supports become (runas), creates interactive subsession under WinRM batch logon
* supports usage of arbitrary module_utils files
* modular exec wrapper payload supports easier extension
* integrates async wrapper behavior for pipelined/become'd async
* module_utils are loaded as true Powershell modules, no more runtime modifications to module code
This commit is contained in:
Matt Davis
2017-02-17 00:09:56 -08:00
committed by GitHub
parent 7bf56ceee3
commit 8527013fbe
17 changed files with 1104 additions and 148 deletions

View File

@@ -33,7 +33,7 @@ from ansible import constants as C
from ansible.compat.six import binary_type, string_types, text_type, iteritems, with_metaclass
from ansible.compat.six.moves import shlex_quote
from ansible.errors import AnsibleError, AnsibleConnectionFailure
from ansible.executor.module_common import modify_module
from ansible.executor.module_common import modify_module, build_windows_module_payload
from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.module_utils.json_utils import _filter_non_json_lines
from ansible.parsing.utils.jsonify import jsonify
@@ -159,6 +159,14 @@ class ActionBase(with_metaclass(ABCMeta, object)):
(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)
# FUTURE: we'll have to get fancier about this to support powershell over SSH on Windows...
if self._connection.transport == "winrm":
# WinRM always pipelines, so we need to build up a fancier module payload...
module_data = build_windows_module_payload(module_name=module_name, module_path=module_path,
b_module_data=module_data, module_args=module_args,
task_vars=task_vars, task=self._task,
play_context=self._play_context)
return (module_style, module_shebang, module_data, module_path)
def _compute_environment_string(self):
@@ -200,6 +208,9 @@ class ActionBase(with_metaclass(ABCMeta, object)):
'''
Determines if we are required and can do pipelining
'''
if self._connection.always_pipeline_modules:
return True #eg, winrm
# any of these require a true
for condition in [
self._connection.has_pipelining,
@@ -610,6 +621,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
self._update_module_args(module_name, module_args, task_vars)
# FUTURE: refactor this along with module build process to better encapsulate "smart wrapper" functionality
(module_style, shebang, module_data, module_path) = self._configure_module(module_name=module_name, module_args=module_args, task_vars=task_vars)
display.vvv("Using module file %s" % module_path)
if not shebang and module_style != 'binary':
@@ -834,10 +846,10 @@ class ActionBase(with_metaclass(ABCMeta, object)):
'''
display.debug("_low_level_execute_command(): starting")
if not cmd:
# this can happen with powershell modules when there is no analog to a Windows command (like chmod)
display.debug("_low_level_execute_command(): no command, exiting")
return dict(stdout='', stderr='', rc=254)
# if not cmd:
# # this can happen with powershell modules when there is no analog to a Windows command (like chmod)
# display.debug("_low_level_execute_command(): no command, exiting")
# return dict(stdout='', stderr='', rc=254)
allow_same_user = C.BECOME_ALLOW_SAME_USER
same_user = self._play_context.become_user == self._play_context.remote_user

View File

@@ -38,8 +38,11 @@ class ActionModule(ActionBase):
# should not be set anymore but here for backwards compatibility
del results['invocation']['module_args']
# FUTURE: better to let _execute_module calculate this internally?
wrap_async = self._task.async and not self._connection.has_native_async
# do work!
results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars, wrap_async=self._task.async))
results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars, wrap_async=wrap_async))
# hack to keep --verbose from showing all the setup module results
# moved from setup module as now we filter out all _ansible_ from results

View File

@@ -83,6 +83,7 @@ class ActionModule(ActionBase):
# add preparation steps to one ssh roundtrip executing the script
env_string = self._compute_environment_string()
script_cmd = ' '.join([env_string, tmp_src, args])
script_cmd = self._connection._shell.wrap_for_exec(script_cmd)
result.update(self._low_level_execute_command(cmd=script_cmd, sudoable=True))