diff options
author | Matt Davis <nitzmahone@users.noreply.github.com> | 2017-06-26 22:57:59 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-26 22:57:59 -0700 |
commit | 6cca156fde59601e4411587b2752254454c601ad (patch) | |
tree | 8bc24862af9da7d1ee3e9aea52d48e1032cc803a /lib/ansible/plugins | |
parent | 940a78c5ba11285ff95314bc436d17fd3e0e5551 (diff) | |
download | ansible-6cca156fde59601e4411587b2752254454c601ad.tar.gz |
re-enable non-pipelined mode for Powershell (#26124)
* fixes #23986
* fixes 3rd-party Windows connection plugins that don't support pipelining (eg awsrun)
(cherry picked from commit 6677559c698f15c582fba80d866f46458848f974)
Diffstat (limited to 'lib/ansible/plugins')
-rw-r--r-- | lib/ansible/plugins/action/__init__.py | 30 | ||||
-rw-r--r-- | lib/ansible/plugins/connection/winrm.py | 12 | ||||
-rw-r--r-- | lib/ansible/plugins/shell/powershell.py | 32 |
3 files changed, 38 insertions, 36 deletions
diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index c530cdee43..5690dabd44 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -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, AnsibleActionSkip, AnsibleActionFail -from ansible.executor.module_common import modify_module, build_windows_module_payload +from ansible.executor.module_common import modify_module 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 @@ -153,18 +153,15 @@ class ActionBase(with_metaclass(ABCMeta, object)): "run 'git pull --rebase' to correct this problem." % (module_name)) # insert shared code and arguments into the module + final_environment = dict() + 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) - - # 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... - final_environment = dict() - self._compute_environment_string(final_environment) - 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, environment=final_environment) + task_vars=task_vars, module_compression=self._play_context.module_compression, + async_timeout=self._task.async, 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) return (module_style, module_shebang, module_data, module_path) @@ -184,7 +181,7 @@ class ActionBase(with_metaclass(ABCMeta, object)): # block then task 'win' in precedence environments.reverse() for environment in environments: - if environment is None: + if environment is None or len(environment) == 0: continue temp_environment = self._templar.template(environment) if not isinstance(temp_environment, dict): @@ -193,7 +190,8 @@ class ActionBase(with_metaclass(ABCMeta, object)): # these environment settings should not need to merge sub-dicts final_environment.update(temp_environment) - final_environment = self._templar.template(final_environment) + if len(final_environment) > 0: + final_environment = self._templar.template(final_environment) if isinstance(raw_environment_out, dict): raw_environment_out.clear() @@ -212,13 +210,11 @@ 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, - self._play_context.pipelining, + self._play_context.pipelining or self._connection.always_pipeline_modules, # pipelining enabled for play or connection requires it (eg winrm) module_style == "new", # old style modules do not support pipelining not C.DEFAULT_KEEP_REMOTE_FILES, # user wants remote files not wrap_async, # async does not support pipelining diff --git a/lib/ansible/plugins/connection/winrm.py b/lib/ansible/plugins/connection/winrm.py index d452be5afd..c97c9ccf6e 100644 --- a/lib/ansible/plugins/connection/winrm.py +++ b/lib/ansible/plugins/connection/winrm.py @@ -326,17 +326,17 @@ class Connection(ConnectionBase): def exec_command(self, cmd, in_data=None, sudoable=True): super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable) - cmd_parts = self._shell._encode_script(exec_wrapper, as_list=True, strict_mode=False, preserve_rc=False) + cmd_parts = self._shell._encode_script(cmd, as_list=True, strict_mode=False, preserve_rc=False) # TODO: display something meaningful here display.vvv("EXEC (via pipeline wrapper)") - if not in_data: - payload = self._create_raw_wrapper_payload(cmd) - else: - payload = in_data + stdin_iterator = None + + if in_data: + stdin_iterator = self._wrapper_payload_stream(in_data) - result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True, stdin_iterator=self._wrapper_payload_stream(payload)) + result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True, stdin_iterator=stdin_iterator) result.std_out = to_bytes(result.std_out) result.std_err = to_bytes(result.std_err) diff --git a/lib/ansible/plugins/shell/powershell.py b/lib/ansible/plugins/shell/powershell.py index 9d9238e4d2..5ad6b86a4d 100644 --- a/lib/ansible/plugins/shell/powershell.py +++ b/lib/ansible/plugins/shell/powershell.py @@ -55,7 +55,8 @@ begin { # stream JSON including become_pw, ps_module_payload, bin_module_payload, become_payload, write_payload_path, preserve directives # exec runspace, capture output, cleanup, return module output - $json_raw = "" + # NB: do not adjust the following line- it is replaced when doing non-streamed module output + $json_raw = '' } process { $input_as_string = [string]$input @@ -332,7 +333,6 @@ Function Run($payload) { $username = $payload.become_user $password = $payload.become_password - Add-Type -TypeDefinition $helper_def Add-Type -TypeDefinition $helper_def -Debug:$false $exec_args = $null @@ -726,7 +726,6 @@ Function Run($payload) { [System.IO.Directory]::CreateDirectory([System.IO.Path]::GetDirectoryName($results_path)) | Out-Null - Add-Type -TypeDefinition $native_process_util Add-Type -TypeDefinition $native_process_util -Debug:$false # FUTURE: create under new job to ensure all children die on exit? @@ -1103,7 +1102,7 @@ class ShellModule(object): def build_module_command(self, env_string, shebang, cmd, arg_path=None, rm_tmp=None): # pipelining bypass if cmd == '': - return '' + return '-' # non-pipelining @@ -1192,15 +1191,22 @@ class ShellModule(object): def _encode_script(self, script, as_list=False, strict_mode=True, preserve_rc=True): '''Convert a PowerShell script to a single base64-encoded command.''' script = to_text(script) - if strict_mode: - script = u'Set-StrictMode -Version Latest\r\n%s' % script - # try to propagate exit code if present- won't work with begin/process/end-style scripts (ala put_file) - # NB: the exit code returned may be incorrect in the case of a successful command followed by an invalid command - if preserve_rc: - script = u'%s\r\nIf (-not $?) { If (Get-Variable LASTEXITCODE -ErrorAction SilentlyContinue) { exit $LASTEXITCODE } Else { exit 1 } }\r\n' % script - script = '\n'.join([x.strip() for x in script.splitlines() if x.strip()]) - encoded_script = base64.b64encode(script.encode('utf-16-le')) - cmd_parts = _common_args + ['-EncodedCommand', encoded_script] + + if script == u'-': + cmd_parts = _common_args + ['-'] + + else: + if strict_mode: + script = u'Set-StrictMode -Version Latest\r\n%s' % script + # try to propagate exit code if present- won't work with begin/process/end-style scripts (ala put_file) + # NB: the exit code returned may be incorrect in the case of a successful command followed by an invalid command + if preserve_rc: + script = u'%s\r\nIf (-not $?) { If (Get-Variable LASTEXITCODE -ErrorAction SilentlyContinue) { exit $LASTEXITCODE } Else { exit 1 } }\r\n'\ + % script + script = '\n'.join([x.strip() for x in script.splitlines() if x.strip()]) + encoded_script = base64.b64encode(script.encode('utf-16-le')) + cmd_parts = _common_args + ['-EncodedCommand', encoded_script] + if as_list: return cmd_parts return ' '.join(cmd_parts) |