From f28b7c7ab1b58201977ee73644f113c1a32cba1b Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Wed, 24 Oct 2018 05:37:05 +1000 Subject: [PATCH] psrp - fix unicode handling in Python 2 (#47461) * psrp - fix unicode handling in Python 2 * skip psrp become test when on Server 2008 --- changelogs/fragments/psrp-utf8.yaml | 2 + lib/ansible/plugins/connection/psrp.py | 34 +++++------ .../targets/connection_psrp/inventory.ini | 3 + .../targets/connection_psrp/runme.sh | 10 ++- .../targets/connection_psrp/tests.yml | 61 +++++++++++++++++++ 5 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 changelogs/fragments/psrp-utf8.yaml create mode 100644 test/integration/targets/connection_psrp/inventory.ini create mode 100644 test/integration/targets/connection_psrp/tests.yml diff --git a/changelogs/fragments/psrp-utf8.yaml b/changelogs/fragments/psrp-utf8.yaml new file mode 100644 index 0000000000..9d32171ae4 --- /dev/null +++ b/changelogs/fragments/psrp-utf8.yaml @@ -0,0 +1,2 @@ +bugfixes: +- psrp - Fix issue when dealing with unicode values in the output for Python 2 diff --git a/lib/ansible/plugins/connection/psrp.py b/lib/ansible/plugins/connection/psrp.py index ff8c5de324..6a36f92d76 100644 --- a/lib/ansible/plugins/connection/psrp.py +++ b/lib/ansible/plugins/connection/psrp.py @@ -553,26 +553,24 @@ if ($bytes_read -gt 0) { # TODO: figure out a better way of merging this with the host output stdout_list = [] for output in pipeline.output: - # not all pipeline outputs can be casted to a string, we will - # create our own output based on the properties if that is the - # case+ - try: - output_msg = str(output) - except TypeError: - if isinstance(output, GenericComplexObject): - obj_lines = output.property_sets - for key, value in output.adapted_properties.items(): - obj_lines.append("%s: %s" % (key, value)) - for key, value in output.extended_properties.items(): - obj_lines.append("%s: %s" % (key, value)) - output_msg = "\n".join(obj_lines) - else: - output_msg = "" + # Not all pipeline outputs are a string or contain a __str__ value, + # we will create our own output based on the properties of the + # complex object if that is the case. + if isinstance(output, GenericComplexObject) and output.to_string is None: + obj_lines = output.property_sets + for key, value in output.adapted_properties.items(): + obj_lines.append(u"%s: %s" % (key, value)) + for key, value in output.extended_properties.items(): + obj_lines.append(u"%s: %s" % (key, value)) + output_msg = u"\n".join(obj_lines) + else: + output_msg = to_text(output, nonstring='simplerepr') + stdout_list.append(output_msg) - stdout = "\r\n".join(stdout_list) + stdout = u"\r\n".join(stdout_list) if len(self.host.ui.stdout) > 0: - stdout += "\r\n" + "".join(self.host.ui.stdout) + stdout += u"\r\n" + u"".join(self.host.ui.stdout) stderr_list = [] for error in pipeline.streams.error: @@ -604,4 +602,4 @@ if ($bytes_read -gt 0) { self.host.ui.stdout = [] self.host.ui.stderr = [] - return rc, stdout, stderr + return rc, to_bytes(stdout, encoding='utf-8'), to_bytes(stderr, encoding='utf-8') diff --git a/test/integration/targets/connection_psrp/inventory.ini b/test/integration/targets/connection_psrp/inventory.ini new file mode 100644 index 0000000000..398a7bd322 --- /dev/null +++ b/test/integration/targets/connection_psrp/inventory.ini @@ -0,0 +1,3 @@ +[windows:vars] +ansible_connection=psrp +ansible_psrp_cert_validation=ignore diff --git a/test/integration/targets/connection_psrp/runme.sh b/test/integration/targets/connection_psrp/runme.sh index 61058c73cd..b5d87061f6 100755 --- a/test/integration/targets/connection_psrp/runme.sh +++ b/test/integration/targets/connection_psrp/runme.sh @@ -2,14 +2,18 @@ set -eux -pip install pypsrp +python.py -m pip install pypsrp cd ../connection INVENTORY=../../inventory.winrm ./test.sh \ + -i ../connection_psrp/inventory.ini \ -e target_hosts=winrm \ -e action_prefix=win_ \ -e local_tmp=/tmp/ansible-local \ -e remote_tmp=c:/windows/temp/ansible-remote \ - -e ansible_psrp_cert_validation=False \ - -c psrp \ + "$@" + +cd ../connection_psrp + +ansible-playbook -i ../../inventory.winrm -i inventory.ini tests.yml \ "$@" diff --git a/test/integration/targets/connection_psrp/tests.yml b/test/integration/targets/connection_psrp/tests.yml new file mode 100644 index 0000000000..c87d339888 --- /dev/null +++ b/test/integration/targets/connection_psrp/tests.yml @@ -0,0 +1,61 @@ +--- +# these are extra tests for psrp that aren't covered under test/integration/targets/connection/* +- name: test out psrp specific tests + hosts: winrm + serial: 1 + gather_facts: no + + tasks: + - name: test complex objects in raw output + # until PyYAML is upgraded to 4.x we need to use the \U escape for a unicode codepoint + # and enclose in a quote to it translates the \U + raw: " + [PSCustomObject]@{string = 'string'}; + [PSCustomObject]@{unicode = 'poo - \U0001F4A9'}; + [PSCustomObject]@{integer = 1}; + [PSCustomObject]@{list = @(1, 2)}; + Get-Service -Name winrm; + Write-Output -InputObject 'string - \U0001F4A9';" + register: raw_out + + - name: assert complex objects in raw output + assert: + that: + - raw_out.stdout_lines|count == 6 + - "raw_out.stdout_lines[0] == 'string: string'" + - "raw_out.stdout_lines[1] == 'unicode: poo - \U0001F4A9'" + - "raw_out.stdout_lines[2] == 'integer: 1'" + - "raw_out.stdout_lines[3] == \"list: [1, 2]\"" + - raw_out.stdout_lines[4] == "winrm" + - raw_out.stdout_lines[5] == "string - \U0001F4A9" + + # Become only works on Server 2008 when running with basic auth, skip this host for now as it is too complicated to + # override the auth protocol in the tests. + - name: check if we running on Server 2008 + win_shell: '[System.Environment]::OSVersion.Version -ge [Version]"6.1"' + register: os_version + + - name: test out become with psrp + win_whoami: + when: os_version|bool + register: whoami_out + become: yes + become_method: runas + become_user: SYSTEM + + - name: assert test out become with psrp + assert: + that: + - whoami_out.account.sid == "S-1-5-18" + when: os_version|bool + + - name: test out async with psrp + win_shell: Start-Sleep -Seconds 2; Write-Output abc + async: 5 + poll: 1 + register: async_out + + - name: assert est out async with psrp + assert: + that: + - async_out.stdout_lines == ["abc"]