Repository: docker/docker-py

Issue:
Support create volume Labels options
First, check the remote API:
https://docs.docker.com/engine/reference/api/docker_remote_api_v1.23/

```
 {
  "Name": "tardis",
  "Labels": {
    "com.example.some-label": "some-value",
    "com.example.some-other-label": "some-other-value"
  },
}
```

It provides `Labels` options. But docker-py doesn't support it right not.

Second, in docker-py's document give the following example:

```
volume = cli.create_volume(
  name='foobar', driver='local', driver_opts={'foo': 'bar', 'baz': 'false'}

docker.errors.APIError: 500 Server Error: Internal Server Error ("create foobar: invalid option key: "foo"")
```

But driver_opts is not working. What kinds of driver_opts can we use?



Discussion:
> But driver_opts is not working. What kinds of driver_opts can we use?

Those should be available here: https://docs.docker.com/engine/admin/logging/overview/ 

These were added "recently", so we don't have support for them yet
@linlinlinlin FYI, `driver_opts` is different. It corresponds to

> DriverOpts - A mapping of driver options and values. These options are passed directly to the driver and are driver specific.

in the docs.

@TomasTomecek those are logging drivers, not volume drivers :pensive: 

@shin Thanks for your support. Is there are any existing DriverOpts as an example we can use in Ubuntu environment? 

Is it possible add these features in 1.9.0 or 1.9.1?

`/facepalm` sorry about the noise, I should read more carefully.


Resolving patch:
diff --git a/docker/api/volume.py b/docker/api/volume.py
--- a/docker/api/volume.py
+++ b/docker/api/volume.py
@@ -1,3 +1,4 @@
+from .. import errors
 from .. import utils
 
 
@@ -11,7 +12,7 @@ def volumes(self, filters=None):
         return self._result(self._get(url, params=params), True)
 
     @utils.minimum_version('1.21')
-    def create_volume(self, name, driver=None, driver_opts=None):
+    def create_volume(self, name, driver=None, driver_opts=None, labels=None):
         url = self._url('/volumes/create')
         if driver_opts is not None and not isinstance(driver_opts, dict):
             raise TypeError('driver_opts must be a dictionary')
@@ -21,6 +22,16 @@ def create_volume(self, name, driver=None, driver_opts=None):
             'Driver': driver,
             'DriverOpts': driver_opts,
         }
+
+        if labels is not None:
+            if utils.compare_version('1.23', self._version) < 0:
+                raise errors.InvalidVersion(
+                    'volume labels were introduced in API 1.23'
+                )
+            if not isinstance(labels, dict):
+                raise TypeError('labels must be a dictionary')
+            data["Labels"] = labels
+
         return self._result(self._post_json(url, data=data), True)
 
     @utils.minimum_version('1.21')


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
@@ -433,7 +433,10 @@ def get_fake_volume():
     response = {
         'Name': 'perfectcherryblossom',
         'Driver': 'local',
-        'Mountpoint': '/var/lib/docker/volumes/perfectcherryblossom'
+        'Mountpoint': '/var/lib/docker/volumes/perfectcherryblossom',
+        'Labels': {
+            'com.example.some-label': 'some-value'
+        }
     }
     return status_code, response
 
diff --git a/tests/unit/volume_test.py b/tests/unit/volume_test.py
--- a/tests/unit/volume_test.py
+++ b/tests/unit/volume_test.py
@@ -43,6 +43,22 @@ def test_create_volume(self):
         self.assertEqual(args[0][1], url_prefix + 'volumes/create')
         self.assertEqual(json.loads(args[1]['data']), {'Name': name})
 
+    @base.requires_api_version('1.23')
+    def test_create_volume_with_labels(self):
+        name = 'perfectcherryblossom'
+        result = self.client.create_volume(name, labels={
+            'com.example.some-label': 'some-value'})
+        self.assertEqual(
+            result["Labels"],
+            {'com.example.some-label': 'some-value'}
+        )
+
+    @base.requires_api_version('1.23')
+    def test_create_volume_with_invalid_labels(self):
+        name = 'perfectcherryblossom'
+        with pytest.raises(TypeError):
+            self.client.create_volume(name, labels=1)
+
     @base.requires_api_version('1.21')
     def test_create_volume_with_driver(self):
         name = 'perfectcherryblossom'