From 9e9407088786e49588c2d06dfb210d97392ea690 Mon Sep 17 00:00:00 2001 From: Jan Losinski Date: Thu, 11 Feb 2016 19:16:58 +0100 Subject: [PATCH 1/8] Add support for Tmpfs declaration in Hostconfig. This adds support for the Tmpfs option introduced in Docker 1.10. See: https://github.com/docker/docker/pull/13587 Signed-off-by: Jan Losinski --- docker/utils/utils.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/docker/utils/utils.py b/docker/utils/utils.py index d4393d584d..a9cd5b7a23 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -337,6 +337,33 @@ def convert_volume_binds(binds): return result +def convert_tmpfs_mounts(tmpfs): + if isinstance(tmpfs, dict): + return tmpfs + + if not isinstance(tmpfs, list): + raise ValueError( + 'Tmpfs spec must be a list' + ) + + result = {} + for mount in tmpfs: + if isinstance(mount, six.string_types): + if ":" in mount: + name, options = mount.split(":", 1) + else: + name = mount + options = "" + + else: + raise ValueError( + "Tmpfs spec have to be str, unicode or tuple" + ) + + result[name] = options + return result + + def parse_repository_tag(repo_name): parts = repo_name.rsplit('@', 1) if len(parts) == 2: @@ -584,7 +611,7 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None, mem_limit=None, memswap_limit=None, mem_swappiness=None, cgroup_parent=None, group_add=None, cpu_quota=None, cpu_period=None, oom_kill_disable=False, shm_size=None, - version=None): + version=None, tmpfs=None): host_config = {} @@ -751,6 +778,9 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None, host_config['CpuPeriod'] = cpu_period + if tmpfs: + host_config["Tmpfs"] = convert_tmpfs_mounts(tmpfs) + return host_config From 72446b47c00c787eb39cb437eeaee7968ad89f31 Mon Sep 17 00:00:00 2001 From: Jan Losinski Date: Thu, 11 Feb 2016 19:20:00 +0100 Subject: [PATCH 2/8] Add unittest for the Tmpfs Hostconfig option Signed-off-by: Jan Losinski --- tests/unit/container_test.py | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/unit/container_test.py b/tests/unit/container_test.py index 6e23f89210..34630b6db1 100644 --- a/tests/unit/container_test.py +++ b/tests/unit/container_test.py @@ -1016,6 +1016,62 @@ def test_create_container_with_aliases(self): } }}''')) + def test_create_container_with_tmpfs_list(self): + + self.client.create_container( + 'busybox', 'true', host_config=self.client.create_host_config( + tmpfs=[ + "/tmp", + "/mnt:size=3G,uid=100" + ] + ) + ) + + args = fake_request.call_args + self.assertEqual(args[0][1], url_prefix + + 'containers/create') + expected_payload = self.base_create_payload() + expected_payload['HostConfig'] = self.client.create_host_config() + expected_payload['HostConfig']['Tmpfs'] = { + "/tmp": "", + "/mnt": "size=3G,uid=100" + } + self.assertEqual(json.loads(args[1]['data']), expected_payload) + self.assertEqual(args[1]['headers'], + {'Content-Type': 'application/json'}) + self.assertEqual( + args[1]['timeout'], + DEFAULT_TIMEOUT_SECONDS + ) + + def test_create_container_with_tmpfs_dict(self): + + self.client.create_container( + 'busybox', 'true', host_config=self.client.create_host_config( + tmpfs={ + "/tmp": "", + "/mnt": "size=3G,uid=100" + } + ) + ) + + args = fake_request.call_args + self.assertEqual(args[0][1], url_prefix + + 'containers/create') + expected_payload = self.base_create_payload() + expected_payload['HostConfig'] = self.client.create_host_config() + expected_payload['HostConfig']['Tmpfs'] = { + "/tmp": "", + "/mnt": "size=3G,uid=100" + } + self.assertEqual(json.loads(args[1]['data']), expected_payload) + self.assertEqual(args[1]['headers'], + {'Content-Type': 'application/json'}) + self.assertEqual( + args[1]['timeout'], + DEFAULT_TIMEOUT_SECONDS + ) + class ContainerTest(DockerClientTest): def test_list_containers(self): From 88ef5f36304d6d6add239e4e0dc60f41bcbf0fcc Mon Sep 17 00:00:00 2001 From: Jan Losinski Date: Thu, 11 Feb 2016 19:20:30 +0100 Subject: [PATCH 3/8] Add documentation for the Tmpfs Hostconfig option. Signed-off-by: Jan Losinski --- docs/hostconfig.md | 2 ++ docs/tmpfs.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 docs/tmpfs.md diff --git a/docs/hostconfig.md b/docs/hostconfig.md index 4b841d51a4..19cd4ca208 100644 --- a/docs/hostconfig.md +++ b/docs/hostconfig.md @@ -111,6 +111,8 @@ for example: container process will run as. * devices (list): Host device bindings. See [host devices](host-devices.md) for more information. +* tmpfs: Temporary filesystems to mouunt. See [Using tmpfs](tmpfs.md) for more + information. **Returns** (dict) HostConfig dictionary diff --git a/docs/tmpfs.md b/docs/tmpfs.md new file mode 100644 index 0000000000..34dadd9ee8 --- /dev/null +++ b/docs/tmpfs.md @@ -0,0 +1,32 @@ +# Using Tmpfs + +Tmpfs declaration is done with the `Client().create_container()` +method by declaring the mountpoints in the `host_config` section. + +This is available from docker 1.10. + +You can provide a list of declarations similar to the `--tmpfs` +option of the docker commandline client: + +```python +container_id = cli.create_container( + 'busybox', 'ls', + host_config=cli.create_host_config(tmpfs=[ + '/mnt/vol2', + '/mnt/vol1:size=3G,uid=1000' + ]) +) +``` + +You can alternatively specify tmpfs as a dict the docker remote +API uses: + +```python +container_id = cli.create_container( + 'busybox', 'ls', + host_config=cli.create_host_config(tmpfs={ + '/mnt/vol2': '', + '/mnt/vol1': 'size=3G,uid=1000' + }) +) +``` From 07455a6a3c92b2c642d340b3356a20c386ad97dc Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Wed, 16 Mar 2016 14:54:32 +0000 Subject: [PATCH 4/8] Clarify error messages when bad values are passed in for tmpfs Signed-off-by: Aanand Prasad --- docker/utils/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docker/utils/utils.py b/docker/utils/utils.py index a9cd5b7a23..04a09a9c5c 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -343,7 +343,8 @@ def convert_tmpfs_mounts(tmpfs): if not isinstance(tmpfs, list): raise ValueError( - 'Tmpfs spec must be a list' + 'Expected tmpfs value to be either a list or a dict, found: {}' + .format(type(tmpfs).__name__) ) result = {} @@ -357,7 +358,8 @@ def convert_tmpfs_mounts(tmpfs): else: raise ValueError( - "Tmpfs spec have to be str, unicode or tuple" + "Expected item in tmpfs list to be a string, found: {}" + .format(type(mount).__name__) ) result[name] = options From a0545092691948fcae34112384c9fc7a5628ca16 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Wed, 16 Mar 2016 15:01:17 +0000 Subject: [PATCH 5/8] Reword tmpfs documentation Signed-off-by: Aanand Prasad --- docs/tmpfs.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/tmpfs.md b/docs/tmpfs.md index 34dadd9ee8..d8be9b68c6 100644 --- a/docs/tmpfs.md +++ b/docs/tmpfs.md @@ -1,30 +1,31 @@ -# Using Tmpfs +# Using tmpfs -Tmpfs declaration is done with the `Client().create_container()` -method by declaring the mountpoints in the `host_config` section. +When creating a container, you can specify paths to be mounted with tmpfs using +the `tmpfs` argument to `create_host_config`, similarly to the `--tmpfs` +argument to `docker run`. -This is available from docker 1.10. +This capability is supported in Docker Engine 1.10 and up. -You can provide a list of declarations similar to the `--tmpfs` -option of the docker commandline client: +`tmpfs` can be either a list or a dictionary. If it's a list, each item is a +string specifying the path and (optionally) any configuration for the mount: ```python -container_id = cli.create_container( +client.create_container( 'busybox', 'ls', - host_config=cli.create_host_config(tmpfs=[ + host_config=client.create_host_config(tmpfs=[ '/mnt/vol2', '/mnt/vol1:size=3G,uid=1000' ]) ) ``` -You can alternatively specify tmpfs as a dict the docker remote -API uses: +Alternatively, if it's a dictionary, each key is a path and each value contains +the mount options: ```python -container_id = cli.create_container( +client.create_container( 'busybox', 'ls', - host_config=cli.create_host_config(tmpfs={ + host_config=client.create_host_config(tmpfs={ '/mnt/vol2': '', '/mnt/vol1': 'size=3G,uid=1000' }) From 4ffa1be825431c51532615bd74b47d92951658c6 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Wed, 16 Mar 2016 15:06:43 +0000 Subject: [PATCH 6/8] Add tmpfs integration test Signed-off-by: Aanand Prasad --- tests/integration/container_test.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/integration/container_test.py b/tests/integration/container_test.py index a1498f9374..940e5b83ff 100644 --- a/tests/integration/container_test.py +++ b/tests/integration/container_test.py @@ -382,6 +382,22 @@ def test_create_with_environment_variable_no_value(self): sorted(['Foo', 'Other=one', 'Blank=']) ) + @requires_api_version('1.22') + def test_create_with_tmpfs(self): + tmpfs = { + '/tmp1': 'size=3M' + } + + container = self.client.create_container( + BUSYBOX, + ['echo'], + host_config=self.client.create_host_config( + tmpfs=tmpfs)) + + self.tmp_containers.append(container['Id']) + config = self.client.inspect_container(container) + assert config['HostConfig']['Tmpfs'] == tmpfs + class VolumeBindTest(helpers.BaseTestCase): def setUp(self): From 7417bc2cceb67d830ecfe2fb541cbd68e4113f17 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Wed, 16 Mar 2016 17:35:08 +0000 Subject: [PATCH 7/8] Don't support tmpfs in API version < 1.22 Signed-off-by: Aanand Prasad --- docker/utils/utils.py | 2 ++ tests/unit/container_test.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docker/utils/utils.py b/docker/utils/utils.py index 04a09a9c5c..c5914cf657 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -781,6 +781,8 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None, host_config['CpuPeriod'] = cpu_period if tmpfs: + if version_lt(version, '1.22'): + raise host_config_version_error('tmpfs', '1.22') host_config["Tmpfs"] = convert_tmpfs_mounts(tmpfs) return host_config diff --git a/tests/unit/container_test.py b/tests/unit/container_test.py index 34630b6db1..2a72c17936 100644 --- a/tests/unit/container_test.py +++ b/tests/unit/container_test.py @@ -1016,6 +1016,7 @@ def test_create_container_with_aliases(self): } }}''')) + @requires_api_version('1.22') def test_create_container_with_tmpfs_list(self): self.client.create_container( @@ -1044,6 +1045,7 @@ def test_create_container_with_tmpfs_list(self): DEFAULT_TIMEOUT_SECONDS ) + @requires_api_version('1.22') def test_create_container_with_tmpfs_dict(self): self.client.create_container( From e576417217c367dfa0b5d33fe7f2886d67b0cbfb Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Wed, 16 Mar 2016 18:27:44 +0000 Subject: [PATCH 8/8] Add tmpfs doc to mkdocs.yml Signed-off-by: Aanand Prasad --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index c6bfae1013..64e9e6cd39 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,6 +13,7 @@ pages: - Host devices: host-devices.md - Host configuration: hostconfig.md - Network configuration: networks.md +- Using tmpfs: tmpfs.md - Using with boot2docker: boot2docker.md - Change Log: change_log.md - Contributing: contributing.md