Repository: ansible/ansible

Issue:
With ansible_python_interpreter python3 docker_login module breaks
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
module docker_login

##### ANSIBLE VERSION
```
ansible 2.3.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.12 (default, Nov 19 2016, 06:48:10) [GCC 5.4.0 20160609]
```

##### CONFIGURATION
ansible_python_interpreter: "/usr/bin/python3"

The installed versions of pip packages on the docker host:

```
pip list --format columns
Package             Version
------------------- -------
cached-property     1.3.0  
colorama            0.3.9  
docker              2.4.2  
docker-compose      1.14.0 
docker-pycreds      0.2.1  
dockerpty           0.4.1  
docopt              0.6.2  
jsonschema          2.6.0  
pip                 9.0.1  
pycurl              7.43.0 
pygobject           3.20.0 
python-apt          1.1.0b1
PyYAML              3.12   
requests            2.11.1 
setuptools          36.0.1 
simplejson          3.8.1  
six                 1.10.0 
texttable           0.8.8  
unattended-upgrades 0.1    
websocket-client    0.44.0 
wheel               0.29.0 
```
##### OS / ENVIRONMENT
Docker image: ubuntu:16.04

##### SUMMARY
The docker_login module fails with python3, but states inside https://docs.ansible.com/ansible/docker_login_module.html that `python >= 2.6` and `docker-py >= 1.7.0` are supported!

##### STEPS TO REPRODUCE

```yaml
- name: Docker post install steps
   hosts: docker_nodes
   tasks:
   - name: Log into DockerHub
        docker_login:
          username: "{{ docker_cloud_username }}"
          password: "{{ docker_cloud_password }}"
          email: "{{ docker_cloud_email }}"
          state: present
```

##### EXPECTED RESULTS
Success

##### ACTUAL RESULTS

```
TASK [Log into DockerHub] ***********************************
task path: /root/core/docker.yml:66
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/cloud/docker/docker_login.py
<> ESTABLISH SSH CONNECTION FOR USER: root
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/cloud/docker/docker_login.py
<> ESTABLISH SSH CONNECTION FOR USER: root
<> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=4422 -o 'IdentityFile="/root/.ssh/id_rsa4096"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/3b98f69a81 <> '/bin/sh -c '"'"'/usr/bin/python3 && sleep 0'"'"''
<> (1, '', 'OpenSSH_7.2p2 Ubuntu-4ubuntu2.2, OpenSSL 1.0.2g  1 Mar 2016\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 25\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 2\r\nTraceback (most recent call last):\n  File "/tmp/ansible_zfnekcpe/ansible_module_docker_login.py", line 334, in <module>\n    main()\n  File "/tmp/ansible_zfnekcpe/ansible_module_docker_login.py", line 325, in main\n    LoginManager(client, results)\n  File "/tmp/ansible_zfnekcpe/ansible_module_docker_login.py", line 168, in __init__\n    self.login()\n  File "/tmp/ansible_zfnekcpe/ansible_module_docker_login.py", line 203, in login\n    self.update_config_file()\n  File "/tmp/ansible_zfnekcpe/ansible_module_docker_login.py", line 280, in update_config_file\n    auth=base64.b64encode(self.username + b\':\' + self.password),\nTypeError: Can\'t convert \'bytes\' object to str implicitly\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 1\r\n')
fatal: [94.130.11.31]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "OpenSSH_7.2p2 Ubuntu-4ubuntu2.2, OpenSSL 1.0.2g  1 Mar 2016\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 25\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 2\r\nTraceback (most recent call last):\n  File \"/tmp/ansible_zfnekcpe/ansible_module_docker_login.py\", line 334, in <module>\n    main()\n  File \"/tmp/ansible_zfnekcpe/ansible_module_docker_login.py\", line 325, in main\n    LoginManager(client, results)\n  File \"/tmp/ansible_zfnekcpe/ansible_module_docker_login.py\", line 168, in __init__\n    self.login()\n  File \"/tmp/ansible_zfnekcpe/ansible_module_docker_login.py\", line 203, in login\n    self.update_config_file()\n  File \"/tmp/ansible_zfnekcpe/ansible_module_docker_login.py\", line 280, in update_config_file\n    auth=base64.b64encode(self.username + b':' + self.password),\nTypeError: Can't convert 'bytes' object to str implicitly\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 1\r\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 1
}
<> (1, '', 'OpenSSH_7.2p2 Ubuntu-4ubuntu2.2, OpenSSL 1.0.2g  1 Mar 2016\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 19\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 2\r\nTraceback (most recent call last):\n  File "/tmp/ansible_zzkf8ez8/ansible_module_docker_login.py", line 334, in <module>\n    main()\n  File "/tmp/ansible_zzkf8ez8/ansible_module_docker_login.py", line 325, in main\n    LoginManager(client, results)\n  File "/tmp/ansible_zzkf8ez8/ansible_module_docker_login.py", line 168, in __init__\n    self.login()\n  File "/tmp/ansible_zzkf8ez8/ansible_module_docker_login.py", line 203, in login\n    self.update_config_file()\n  File "/tmp/ansible_zzkf8ez8/ansible_module_docker_login.py", line 280, in update_config_file\n    auth=base64.b64encode(self.username + b\':\' + self.password),\nTypeError: Can\'t convert \'bytes\' object to str implicitly\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 1\r\n')
<> (1, '', 'OpenSSH_7.2p2 Ubuntu-4ubuntu2.2, OpenSSL 1.0.2g  1 Mar 2016\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 22\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 2\r\nTraceback (most recent call last):\n  File "/tmp/ansible_112dub7t/ansible_module_docker_login.py", line 334, in <module>\n    main()\n  File "/tmp/ansible_112dub7t/ansible_module_docker_login.py", line 325, in main\n    LoginManager(client, results)\n  File "/tmp/ansible_112dub7t/ansible_module_docker_login.py", line 168, in __init__\n    self.login()\n  File "/tmp/ansible_112dub7t/ansible_module_docker_login.py", line 203, in login\n    self.update_config_file()\n  File "/tmp/ansible_112dub7t/ansible_module_docker_login.py", line 280, in update_config_file\n    auth=base64.b64encode(self.username + b\':\' + self.password),\nTypeError: Can\'t convert \'bytes\' object to str implicitly\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 1\r\n')
```



Discussion:
cc @olsaki
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
cc @jctanner
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/cloud/docker/docker_login.py b/lib/ansible/modules/cloud/docker/docker_login.py
--- a/lib/ansible/modules/cloud/docker/docker_login.py
+++ b/lib/ansible/modules/cloud/docker/docker_login.py
@@ -143,6 +143,7 @@
 
 import base64
 
+from ansible.module_utils._text import to_bytes, to_text
 from ansible.module_utils.docker_common import *
 
 
@@ -276,8 +277,13 @@ def update_config_file(self):
             self.log("Adding registry_url %s to auths." % (self.registry_url))
             config['auths'][self.registry_url] = dict()
 
+        b64auth = base64.b64encode(
+            to_bytes(self.username) + b':' + to_bytes(self.password)
+        )
+        auth = to_text(b64auth)
+
         encoded_credentials = dict(
-            auth=base64.b64encode(self.username + b':' + self.password),
+            auth=auth,
             email=self.email
         )
 


Test patch: