Repository: ansible/ansible

Issue:
Ansible Galaxy Init Fails in Python 3
##### ISSUE TYPE

 - Bug Report

##### COMPONENT NAME

`ansible-galaxy`

##### ANSIBLE VERSION

```
$ ansible --version
ansible 2.2.0.0
  config file =
  configured module search path = Default w/o overrides
```

##### CONFIGURATION

None.

##### OS / ENVIRONMENT

Python 3.5.2, Ubuntu 16.04.

##### SUMMARY

Installing Ansible with `pip install ansible` on Ubuntu 16.04, then trying to create roles with `ansible-galaxy init --force rolename` fails with an encoding error.

##### STEPS TO REPRODUCE

```
$ ansible-galaxy init --force example
ERROR! Could not process data from the API server (https://galaxy.ansible.com/api/): the JSON object must be str, not 'bytes'
```

The issue is [here](https://github.com/ansible/ansible/blob/devel/lib/ansible/galaxy/api.py#L122).

##### EXPECTED RESULTS

I expected it to successfully create a role.

##### ACTUAL RESULTS

```
$ ansible-galaxy init -vvvvv --force example
No config file found; using defaults
Opened /home/naftuli/.ansible_galaxy
Initial connection to galaxy_server: https://galaxy.ansible.com
ERROR! Could not process data from the API server (https://galaxy.ansible.com/api/): the JSON object must be str, not 'bytes'
```

This is a simple Python 3 issue.


Discussion:

Resolving patch:
diff --git a/lib/ansible/galaxy/api.py b/lib/ansible/galaxy/api.py
--- a/lib/ansible/galaxy/api.py
+++ b/lib/ansible/galaxy/api.py
@@ -32,7 +32,7 @@
 from ansible.compat.six.moves.urllib.parse import quote as urlquote, urlencode
 from ansible.errors import AnsibleError
 from ansible.galaxy.token import GalaxyToken
-from ansible.module_utils._text import to_native
+from ansible.module_utils._text import to_native, to_text
 from ansible.module_utils.urls import open_url
 
 try:
@@ -93,7 +93,7 @@ def __call_galaxy(self, url, args=None, headers=None, method=None):
             display.vvv(url)
             resp = open_url(url, data=args, validate_certs=self._validate_certs, headers=headers, method=method,
                             timeout=20)
-            data = json.load(resp)
+            data = json.load(to_text(resp, errors='surrogate_or_strict'))
         except HTTPError as e:
             res = json.load(e)
             raise AnsibleError(res['detail'])
@@ -119,7 +119,7 @@ def _get_server_api_version(self):
             raise AnsibleError("Failed to get data from the API server (%s): %s " % (url, to_native(e)))
 
         try:
-            data = json.load(return_data)
+            data = json.load(to_text(return_data, errors='surrogate_or_strict'))
         except Exception as e:
             raise AnsibleError("Could not process data from the API server (%s): %s " % (url, to_native(e)))
 
@@ -136,7 +136,7 @@ def authenticate(self, github_token):
         url = '%s/tokens/' % self.baseurl
         args = urlencode({"github_token": github_token})
         resp = open_url(url, data=args, validate_certs=self._validate_certs, method="POST")
-        data = json.load(resp)
+        data = json.load(to_text(resp, errors='surrogate_or_strict'))
         return data
 
     @g_connect


Test patch: