From 441dc369ba0f0080edf3e54235319765517e945a Mon Sep 17 00:00:00 2001 From: nathaniel gentile Date: Fri, 15 Dec 2017 14:17:15 -0800 Subject: [PATCH] py3 compatibility: convert bytes to str (#33206) Fixes #31723 In python3, ansible's fetch_url utility function wraps urllib.request.urlopen. For HTTP and HTTPS URLs, this function returns a http.client.HTTPResponse object slightly modified. Calling .read() on an HTTPResponse object returns bytes (note the docstring fix). Here, to_native is used to convert the bytestrings returned by fetch_url into unicode strings. This is necessary because: 1. Pre python3.6, json.loads requires passing a string, not a bytestring, as its argument 2. In python3 generally, testing if a string is a substring of a bytestring using the 'in' operator will raise a TypeError see: - https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen - https://docs.python.org/3/library/http.client.html#http.client.HTTPResponse.read - https://docs.python.org/3/library/json.html#json.loads --- lib/ansible/module_utils/urls.py | 2 +- lib/ansible/modules/web_infrastructure/jenkins_script.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/ansible/module_utils/urls.py b/lib/ansible/module_utils/urls.py index 8884fe3b936..c6323931c7e 100644 --- a/lib/ansible/module_utils/urls.py +++ b/lib/ansible/module_utils/urls.py @@ -941,7 +941,7 @@ def fetch_url(module, url, data=None, headers=None, method=None, :kwarg last_mod_time: Default: None :kwarg int timeout: Default: 10 - :returns: A tuple of (**response**, **info**). Use ``response.body()`` to read the data. + :returns: A tuple of (**response**, **info**). Use ``response.read()`` to read the data. The **info** contains the 'status' and other meta data. When a HttpError (status > 400) occurred then ``info['body']`` contains the error response data:: diff --git a/lib/ansible/modules/web_infrastructure/jenkins_script.py b/lib/ansible/modules/web_infrastructure/jenkins_script.py index 85c0ba5fa89..70cea925d7f 100644 --- a/lib/ansible/modules/web_infrastructure/jenkins_script.py +++ b/lib/ansible/modules/web_infrastructure/jenkins_script.py @@ -116,6 +116,7 @@ import json from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six.moves.urllib.parse import urlencode from ansible.module_utils.urls import fetch_url +from ansible.module_utils._text import to_native def is_csrf_protection_enabled(module): @@ -125,7 +126,7 @@ def is_csrf_protection_enabled(module): if info["status"] != 200: module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"]) - content = resp.read() + content = to_native(resp.read()) return json.loads(content).get('useCrumbs', False) @@ -136,7 +137,7 @@ def get_crumb(module): if info["status"] != 200: module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"]) - content = resp.read() + content = to_native(resp.read()) return json.loads(content) @@ -182,7 +183,7 @@ def main(): if info["status"] != 200: module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"]) - result = resp.read() + result = to_native(resp.read()) if 'Exception:' in result and 'at java.lang.Thread' in result: module.fail_json(msg="script failed with stacktrace:\n " + result)