Ver código fonte

Support volume_driver in compose

* Add support for volume_driver parameter in compose yml
* Don't expand volume host paths if a volume_driver is specified
  (i.e., disable compose feature "relative to absolute path
  transformation" when volume drivers are in use, since volume drivers
  can use name where host path is normally specified; this is a
  heuristic)

Signed-off-by: Luke Marsden <[email protected]>
Luke Marsden 10 anos atrás
pai
commit
a68ee0d9c2
4 arquivos alterados com 33 adições e 2 exclusões
  1. 2 1
      compose/config.py
  2. 9 1
      docs/yml.md
  3. 6 0
      tests/integration/service_test.py
  4. 16 0
      tests/unit/config_test.py

+ 2 - 1
compose/config.py

@@ -43,6 +43,7 @@ DOCKER_CONFIG_KEYS = [
     'stdin_open',
     'tty',
     'user',
+    'volume_driver',
     'volumes',
     'volumes_from',
     'working_dir',
@@ -251,7 +252,7 @@ def process_container_options(service_dict, working_dir=None):
     if 'memswap_limit' in service_dict and 'mem_limit' not in service_dict:
         raise ConfigurationError("Invalid 'memswap_limit' configuration for %s service: when defining 'memswap_limit' you must set 'mem_limit' as well" % service_dict['name'])
 
-    if 'volumes' in service_dict:
+    if 'volumes' in service_dict and service_dict.get('volume_driver') is None:
         service_dict['volumes'] = resolve_volume_paths(service_dict['volumes'], working_dir=working_dir)
 
     if 'build' in service_dict:

+ 9 - 1
docs/yml.md

@@ -134,6 +134,12 @@ Mount paths as volumes, optionally specifying a path on the host machine
      - cache/:/tmp/cache
      - ~/configs:/etc/configs/:ro
 
+You can mount a relative path on the host, which will expand relative to
+the directory of the Compose configuration file being used.
+
+> Note: No path expansion will be done if you have also specified a
+> `volume_driver`.
+
 ### volumes_from
 
 Mount all of the volumes from another service or container.
@@ -333,7 +339,7 @@ Override the default labeling scheme for each container.
         - label:user:USER
         - label:role:ROLE
 
-### working\_dir, entrypoint, user, hostname, domainname, mac\_address, mem\_limit, memswap\_limit, privileged, restart, stdin\_open, tty, cpu\_shares, cpuset, read\_only 
+### working\_dir, entrypoint, user, hostname, domainname, mac\_address, mem\_limit, memswap\_limit, privileged, restart, stdin\_open, tty, cpu\_shares, cpuset, read\_only, volume\_driver
 
 Each of these is a single value, analogous to its
 [docker run](https://docs.docker.com/reference/run/) counterpart.
@@ -360,6 +366,8 @@ Each of these is a single value, analogous to its
     tty: true
     read_only: true
 
+    volume_driver: mydriver
+```
 
 ## Compose documentation
 

+ 6 - 0
tests/integration/service_test.py

@@ -117,6 +117,12 @@ class ServiceTest(DockerClientTestCase):
         service.start_container(container)
         self.assertIn('/var/db', container.get('Volumes'))
 
+    def test_create_container_with_volume_driver(self):
+        service = self.create_service('db', volume_driver='foodriver')
+        container = service.create_container()
+        service.start_container(container)
+        self.assertEqual('foodriver', container.get('Config.VolumeDriver'))
+
     def test_create_container_with_cpu_shares(self):
         service = self.create_service('db', cpu_shares=73)
         container = service.create_container()

+ 16 - 0
tests/unit/config_test.py

@@ -72,6 +72,22 @@ class VolumePathTest(unittest.TestCase):
         d = make_service_dict('foo', {'volumes': ['~:/container/path']}, working_dir='.')
         self.assertEqual(d['volumes'], ['/home/user:/container/path'])
 
+    def test_named_volume_with_driver(self):
+        d = make_service_dict('foo', {
+            'volumes': ['namedvolume:/data'],
+            'volume_driver': 'foodriver',
+        }, working_dir='.')
+        self.assertEqual(d['volumes'], ['namedvolume:/data'])
+
+    @mock.patch.dict(os.environ)
+    def test_named_volume_with_special_chars(self):
+        os.environ['NAME'] = 'surprise!'
+        d = make_service_dict('foo', {
+            'volumes': ['~/${NAME}:/data'],
+            'volume_driver': 'foodriver',
+        }, working_dir='.')
+        self.assertEqual(d['volumes'], ['~/${NAME}:/data'])
+
 
 class MergePathMappingTest(object):
     def config_name(self):