diff options
author | Joffrey F <joffrey@docker.com> | 2017-10-24 16:17:25 -0700 |
---|---|---|
committer | Joffrey F <f.joffrey@gmail.com> | 2017-11-07 15:18:26 -0800 |
commit | 5d1b6522462c6672482555b479630f3a4c6b7dcf (patch) | |
tree | 55190e8201ebe081cc3a4ee0f1d2ff649b3c01ac | |
parent | eee9cbbf0810fed71f68bac3fd4d93cfe16208a5 (diff) | |
download | docker-py-5d1b6522462c6672482555b479630f3a4c6b7dcf.tar.gz |
Add support for mounts in HostConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
-rw-r--r-- | docker/api/container.py | 4 | ||||
-rw-r--r-- | docker/models/containers.py | 5 | ||||
-rw-r--r-- | docker/types/containers.py | 7 | ||||
-rw-r--r-- | tests/integration/api_container_test.py | 65 |
4 files changed, 80 insertions, 1 deletions
diff --git a/docker/api/container.py b/docker/api/container.py index 918f8a3..f3c33c9 100644 --- a/docker/api/container.py +++ b/docker/api/container.py @@ -529,6 +529,10 @@ class ContainerApiMixin(object): behavior. Accepts number between 0 and 100. memswap_limit (str or int): Maximum amount of memory + swap a container is allowed to consume. + mounts (:py:class:`list`): Specification for mounts to be added to + the container. More powerful alternative to ``binds``. Each + item in the list is expected to be a + :py:class:`docker.types.Mount` object. network_mode (str): One of: - ``bridge`` Create a new network stack for the container on diff --git a/docker/models/containers.py b/docker/models/containers.py index 688decc..ea8c10b 100644 --- a/docker/models/containers.py +++ b/docker/models/containers.py @@ -549,6 +549,10 @@ class ContainerCollection(Collection): behavior. Accepts number between 0 and 100. memswap_limit (str or int): Maximum amount of memory + swap a container is allowed to consume. + mounts (:py:class:`list`): Specification for mounts to be added to + the container. More powerful alternative to ``volumes``. Each + item in the list is expected to be a + :py:class:`docker.types.Mount` object. name (str): The name for this container. nano_cpus (int): CPU quota in units of 10-9 CPUs. network (str): Name of the network this container will be connected @@ -888,6 +892,7 @@ RUN_HOST_CONFIG_KWARGS = [ 'mem_reservation', 'mem_swappiness', 'memswap_limit', + 'mounts', 'nano_cpus', 'network_mode', 'oom_kill_disable', diff --git a/docker/types/containers.py b/docker/types/containers.py index 030e292..3fc13d9 100644 --- a/docker/types/containers.py +++ b/docker/types/containers.py @@ -120,7 +120,7 @@ class HostConfig(dict): isolation=None, auto_remove=False, storage_opt=None, init=None, init_path=None, volume_driver=None, cpu_count=None, cpu_percent=None, nano_cpus=None, - cpuset_mems=None, runtime=None): + cpuset_mems=None, runtime=None, mounts=None): if mem_limit is not None: self['Memory'] = parse_bytes(mem_limit) @@ -478,6 +478,11 @@ class HostConfig(dict): raise host_config_version_error('runtime', '1.25') self['Runtime'] = runtime + if mounts is not None: + if version_lt(version, '1.30'): + raise host_config_version_error('mounts', '1.30') + self['Mounts'] = mounts + def host_config_type_error(param, param_value, expected): error_msg = 'Invalid type for {0} param: expected {1} but found {2}' diff --git a/tests/integration/api_container_test.py b/tests/integration/api_container_test.py index a972c1c..f03ccdb 100644 --- a/tests/integration/api_container_test.py +++ b/tests/integration/api_container_test.py @@ -522,6 +522,71 @@ class VolumeBindTest(BaseAPIIntegrationTest): inspect_data = self.client.inspect_container(container) self.check_container_data(inspect_data, False) + @pytest.mark.xfail( + IS_WINDOWS_PLATFORM, reason='Test not designed for Windows platform' + ) + @requires_api_version('1.30') + def test_create_with_mounts(self): + mount = docker.types.Mount( + type="bind", source=self.mount_origin, target=self.mount_dest + ) + host_config = self.client.create_host_config(mounts=[mount]) + container = self.run_container( + BUSYBOX, ['ls', self.mount_dest], + host_config=host_config + ) + assert container + logs = self.client.logs(container) + if six.PY3: + logs = logs.decode('utf-8') + assert self.filename in logs + inspect_data = self.client.inspect_container(container) + self.check_container_data(inspect_data, True) + + @pytest.mark.xfail( + IS_WINDOWS_PLATFORM, reason='Test not designed for Windows platform' + ) + @requires_api_version('1.30') + def test_create_with_mounts_ro(self): + mount = docker.types.Mount( + type="bind", source=self.mount_origin, target=self.mount_dest, + read_only=True + ) + host_config = self.client.create_host_config(mounts=[mount]) + container = self.run_container( + BUSYBOX, ['ls', self.mount_dest], + host_config=host_config + ) + assert container + logs = self.client.logs(container) + if six.PY3: + logs = logs.decode('utf-8') + assert self.filename in logs + inspect_data = self.client.inspect_container(container) + self.check_container_data(inspect_data, False) + + @requires_api_version('1.30') + def test_create_with_volume_mount(self): + mount = docker.types.Mount( + type="volume", source=helpers.random_name(), + target=self.mount_dest, labels={'com.dockerpy.test': 'true'} + ) + host_config = self.client.create_host_config(mounts=[mount]) + container = self.client.create_container( + BUSYBOX, ['true'], host_config=host_config, + ) + assert container + inspect_data = self.client.inspect_container(container) + assert 'Mounts' in inspect_data + filtered = list(filter( + lambda x: x['Destination'] == self.mount_dest, + inspect_data['Mounts'] + )) + assert len(filtered) == 1 + mount_data = filtered[0] + assert mount['Source'] == mount_data['Name'] + assert mount_data['RW'] is True + def check_container_data(self, inspect_data, rw): if docker.utils.compare_version('1.20', self.client._version) < 0: self.assertIn('Volumes', inspect_data) |