Repository: docker/docker-py

Issue:
Couldn't create secret object
I couldn't create secret object, the problem seemed to boil down to the way that a secret was being created from the docker daemon response. 

https://github.com/docker/docker-py/blob/467cacb00d8dce68aa8ff2bdacc85acecd2d1207/docker/models/secrets.py#L31-L33

Docker version 18.03.1-ce and python version 3.5 had the following error:

````
File "docker/models/secrets.py", line 10 in __repr__
return "<%s: %s'>" % (self.__class__.__name__, self.name)
File "docker/models/secrets.py", line 14 in name
return self.attrs['Spec']['Name']
KeyError: 'Spec'

````

When calling: 

````
import docker

client -docker.from_env()
mySecret = client.secrets.create(name='randomName', data='platform_node_requirements.md')

````

Changing the code to the following seemed to fix it. 
````
obj = self.client.api.create_secret(**kwargs)
secret = self.client.secrets.get(obj.get('ID'))
return self.prepare_model(secret)
````





Discussion:
Master branch is working.
I get the same error for `client.configs.create`

docker version: `19.03.5 633a0ea`
docker-py version: `4.1.0`

On my side the creation works but the `__repr__` method seem to expect a name where the returned object only contains the id attr. Not too bad but it could be handled more gracefully. For example you will get an ugly exception every time you create a secret from an interactive python shell without assigning the returned value.

```python
>>> import docker
>>> d = docker.from_env()

>>> s = d.secrets.create(name="test", data="ok")
>>> s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/user/Library/Caches/pypoetry/virtualenvs/whatever-py3.7/lib/python3.7/site-packages/docker/models/secrets.py", line 10, in __repr__
    return "<%s: '%s'>" % (self.__class__.__name__, self.name)
  File "/Users/user/Library/Caches/pypoetry/virtualenvs/whatever-py3.7/lib/python3.7/site-packages/docker/models/secrets.py", line 14, in name
    return self.attrs['Spec']['Name']
KeyError: 'Spec'
>>> s.attrs
{'ID': 'wi2jpy7n70wkkrbytnbctv1nj'}

>>> d.secrets.create(name="test2", data="ok")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/user/Library/Caches/pypoetry/virtualenvs/whatever-py3.7/lib/python3.7/site-packages/docker/models/secrets.py", line 10, in __repr__
    return "<%s: '%s'>" % (self.__class__.__name__, self.name)
  File "/Users/user/Library/Caches/pypoetry/virtualenvs/whatever-py3.7/lib/python3.7/site-packages/docker/models/secrets.py", line 14, in name
    return self.attrs['Spec']['Name']
KeyError: 'Spec'
```
Hi @etienne-napoleone 

I opened a [PR](https://github.com/docker/docker-py/pull/2470) for that issue. Do you want to review it?
Thanks.

Resolving patch:
diff --git a/docker/models/secrets.py b/docker/models/secrets.py
--- a/docker/models/secrets.py
+++ b/docker/models/secrets.py
@@ -30,6 +30,7 @@ class SecretCollection(Collection):
 
     def create(self, **kwargs):
         obj = self.client.api.create_secret(**kwargs)
+        obj.setdefault("Spec", {})["Name"] = kwargs.get("name")
         return self.prepare_model(obj)
     create.__doc__ = APIClient.create_secret.__doc__
 


Test patch:
diff --git a/tests/unit/fake_api.py b/tests/unit/fake_api.py
--- a/tests/unit/fake_api.py
+++ b/tests/unit/fake_api.py
@@ -17,6 +17,8 @@
 FAKE_PATH = '/path'
 FAKE_VOLUME_NAME = 'perfectcherryblossom'
 FAKE_NODE_ID = '24ifsmvkjbyhk'
+FAKE_SECRET_ID = 'epdyrw4tsi03xy3deu8g8ly6o'
+FAKE_SECRET_NAME = 'super_secret'
 
 # Each method is prefixed with HTTP method (get, post...)
 # for clarity and readability
@@ -512,6 +514,12 @@ def post_fake_network_disconnect():
     return 200, None
 
 
+def post_fake_secret():
+    status_code = 200
+    response = {'ID': FAKE_SECRET_ID}
+    return status_code, response
+
+
 # Maps real api url to fake response callback
 prefix = 'http+docker://localhost'
 if constants.IS_WINDOWS_PLATFORM:
@@ -643,4 +651,6 @@ def post_fake_network_disconnect():
         CURRENT_VERSION, prefix, FAKE_NETWORK_ID
     ), 'POST'):
     post_fake_network_disconnect,
+    '{1}/{0}/secrets/create'.format(CURRENT_VERSION, prefix):
+    post_fake_secret,
 }
diff --git a/tests/unit/fake_api_client.py b/tests/unit/fake_api_client.py
--- a/tests/unit/fake_api_client.py
+++ b/tests/unit/fake_api_client.py
@@ -40,6 +40,7 @@ def make_fake_api_client(overrides=None):
             fake_api.post_fake_create_container()[1],
         'create_host_config.side_effect': api_client.create_host_config,
         'create_network.return_value': fake_api.post_fake_network()[1],
+        'create_secret.return_value': fake_api.post_fake_secret()[1],
         'exec_create.return_value': fake_api.post_fake_exec_create()[1],
         'exec_start.return_value': fake_api.post_fake_exec_start()[1],
         'images.return_value': fake_api.get_fake_images()[1],
diff --git a/tests/unit/models_secrets_test.py b/tests/unit/models_secrets_test.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/models_secrets_test.py
@@ -0,0 +1,11 @@
+import unittest
+
+from .fake_api_client import make_fake_client
+from .fake_api import FAKE_SECRET_NAME
+
+
+class CreateServiceTest(unittest.TestCase):
+    def test_secrets_repr(self):
+        client = make_fake_client()
+        secret = client.secrets.create(name="super_secret", data="secret")
+        assert secret.__repr__() == "<Secret: '{}'>".format(FAKE_SECRET_NAME)