Repository: docker/docker-py

Issue:
login failed with default registry
I am using docker-py (1.8.0) and trying to using login API.

If I don't input `registry='https://index.docker.io/v1/'` .
It will raise exception as following:

```
docker.errors.APIError: 500 Server Error: Internal Server Error ("Unexpected status code [301] :")
```

But I saw https://github.com/docker/docker-py/blob/81edb398ebf7ce5c7ef14aa0739de5329589aabe/docker/api/daemon.py#L52 in source code. Should work with default registry.



Discussion:
Looks like that the default URL is wrong:

```
$ curl -v -XHEAD https://docker.io/v1/
*   Trying 52.4.72.58...
* Connected to docker.io (52.4.72.58) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*       subject: CN=*.docker.io,OU=Domain Control Validated - RapidSSL(R),OU=See www.rapidssl.com/resources/cps (c)15,OU=GT98568428
*       start date: Mar 19 17:34:32 2015 GMT
*       expire date: Apr 21 01:51:52 2018 GMT
*       common name: *.docker.io
*       issuer: CN=RapidSSL SHA256 CA - G3,O=GeoTrust Inc.,C=US
> HEAD /v1/ HTTP/1.1
> User-Agent: curl/7.40.0
> Host: docker.io
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Content-length: 0
< Location: https://www.docker.com/v1/
< Connection: close
<
* Closing connection 0
```

Even `docker info` says `index`:

```
$ docker info
...
Registry: https://index.docker.io/v1/
```

We changed it a couple versions ago here: https://github.com/docker/docker-py/pull/874
It's odd that this would cause an issue, but I'll look into it. Thanks for the report.

Another question, whatever I set  `dockercfg_path (str)` or not.

I didn't see any configure file at `$HOME/.dockercfg` or any path I set.

@linlinlinlin docker-py doesn't modify your configuration file 
If you call `login()`, it will simply keep the information for the duration of the session (as part of the Client instance) in memory, but we don't write in the JSON file.

@shin Thanks for your information. 

I might misunderstand the description of API doc. It just use it but not save it, right? i.e. at `/home/user/.docker/config.json`

```
dockercfg_path (str): Use a custom path for the .dockercfg file (default $HOME/.dockercfg)
```

So, if I restart my client process, I have to re-login again then I can do push image.

I've been trying to reproduce the error but I haven't been able to do so. The current code seems to work just fine ( docker-py 1.8.0, docker 1.11.0).
Are you still seeing the issue?

``` python
In [1]: import docker

In [2]: c = docker.Client()

In [3]: c.login('joffrey', reauth=True)
Out[3]: {u'Status': u'Login Succeeded'}
```

docker-py 1.8.0, docker 1.10.2

``` python
In [1]: import docker

In [2]: c = docker.Client()

In [3]: c.login('joffrey', reauth=True)
---------------------------------------------------------------------------
APIError                                  Traceback (most recent call last)
<ipython-input-3-5c357d05484c> in <module>()
----> 1 c.login('joffrey', reauth=True)

/home/vagrant/.local/share/virtualenvs/aaa/lib/python2.7/site-packages/docker/api/daemon.pyc in login(self, username, password, email, registry, reauth, insecure_registry, dockercfg_path)
     69         if response.status_code == 200:
     70             self._auth_configs[registry] = req_data
---> 71         return self._result(response, json=True)
     72 
     73     def ping(self):

/home/vagrant/.local/share/virtualenvs/aaa/lib/python2.7/site-packages/docker/client.pyc in _result(self, response, json, binary)
    156     def _result(self, response, json=False, binary=False):
    157         assert not (json and binary)
--> 158         self._raise_for_status(response)
    159 
    160         if json:

/home/vagrant/.local/share/virtualenvs/aaa/lib/python2.7/site-packages/docker/client.pyc in _raise_for_status(self, response, explanation)
    152             if e.response.status_code == 404:
    153                 raise errors.NotFound(e, response, explanation=explanation)
--> 154             raise errors.APIError(e, response, explanation=explanation)
    155 
    156     def _result(self, response, json=False, binary=False):

APIError: 500 Server Error: Internal Server Error ("Unexpected status code [301] :")

In [4]: docker.version
Out[4]: '1.8.0'
```

``` python
In [2]: import docker

In [3]: c = docker.Client()

In [4]: c.login('joffrey', reauth=True, registry='https://index.docker.io/v1/')
---------------------------------------------------------------------------
APIError                                  Traceback (most recent call last)
<ipython-input-4-bce50e4b242e> in <module>()
----> 1 c.login('joffrey', reauth=True, registry='https://index.docker.io/v1/')

/home/vagrant/.local/share/virtualenvs/aaa/lib/python2.7/site-packages/docker/api/daemon.pyc in login(self, username, password, email, registry, reauth, insecure_registry, dockercfg_path)
     69         if response.status_code == 200:
     70             self._auth_configs[registry] = req_data
---> 71         return self._result(response, json=True)
     72 
     73     def ping(self):

/home/vagrant/.local/share/virtualenvs/aaa/lib/python2.7/site-packages/docker/client.pyc in _result(self, response, json, binary)
    156     def _result(self, response, json=False, binary=False):
    157         assert not (json and binary)
--> 158         self._raise_for_status(response)
    159 
    160         if json:

/home/vagrant/.local/share/virtualenvs/aaa/lib/python2.7/site-packages/docker/client.pyc in _raise_for_status(self, response, explanation)
    152             if e.response.status_code == 404:
    153                 raise errors.NotFound(e, response, explanation=explanation)
--> 154             raise errors.APIError(e, response, explanation=explanation)
    155 
    156     def _result(self, response, json=False, binary=False):

APIError: 500 Server Error: Internal Server Error ("Registration: "Missing password field"")
```

Ok, I just tried with 1.10.2, and I can reproduce the issue.
Since this is fixed in 1.11 and can be worked around for 1.10 (by specifying the registry manually), I don't think it is necessary to do anything.


Resolving patch:
diff --git a/docker/api/daemon.py b/docker/api/daemon.py
--- a/docker/api/daemon.py
+++ b/docker/api/daemon.py
@@ -49,8 +49,6 @@ def login(self, username, password=None, email=None, registry=None,
         elif not self._auth_configs:
             self._auth_configs = auth.load_config()
 
-        registry = registry or auth.INDEX_URL
-
         authcfg = auth.resolve_authconfig(self._auth_configs, registry)
         # If we found an existing auth config for this registry and username
         # combination, we can return it immediately unless reauth is requested.
@@ -67,7 +65,7 @@ def login(self, username, password=None, email=None, registry=None,
 
         response = self._post_json(self._url('/auth'), data=req_data)
         if response.status_code == 200:
-            self._auth_configs[registry] = req_data
+            self._auth_configs[registry or auth.INDEX_NAME] = req_data
         return self._result(response, json=True)
 
     def ping(self):


Test patch: