From fc26982132b4a08f4efa2365a8cd668f94ff004e Mon Sep 17 00:00:00 2001 From: Mazz Mosley Date: Mon, 6 Jul 2015 17:07:31 +0100 Subject: [PATCH] Add in memswap_limit run option By allowing the memswap_limit option to be defined we also need to check that mem_limit is set, you can't have swap without a limit. Signed-off-by: Mazz Mosley --- compose/config.py | 5 +++++ docs/yml.md | 3 ++- tests/unit/config_test.py | 25 +++++++++++++++++++++++++ tests/unit/service_test.py | 7 +++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/compose/config.py b/compose/config.py index 7fceb50cc57..d04903db2db 100644 --- a/compose/config.py +++ b/compose/config.py @@ -31,6 +31,7 @@ 'links', 'mac_address', 'mem_limit', + 'memswap_limit', 'net', 'log_driver', 'pid', @@ -61,6 +62,7 @@ 'extra_host': 'extra_hosts', 'device': 'devices', 'link': 'links', + 'memory_swap': 'memswap_limit', 'port': 'ports', 'privilege': 'privileged', 'priviliged': 'privileged', @@ -244,6 +246,9 @@ def process_container_options(service_dict, working_dir=None): service_dict = service_dict.copy() + 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: service_dict['volumes'] = resolve_volume_paths(service_dict['volumes'], working_dir=working_dir) diff --git a/docs/yml.md b/docs/yml.md index 02540b3ff13..4bab73b2b18 100644 --- a/docs/yml.md +++ b/docs/yml.md @@ -312,7 +312,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, 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 Each of these is a single value, analogous to its [docker run](https://docs.docker.com/reference/run/) counterpart. @@ -330,6 +330,7 @@ Each of these is a single value, analogous to its mac_address: 02:42:ac:11:65:43 mem_limit: 1000000000 + memswap_limit: 2000000000 privileged: true restart: always diff --git a/tests/unit/config_test.py b/tests/unit/config_test.py index d56b2a18133..281717db746 100644 --- a/tests/unit/config_test.py +++ b/tests/unit/config_test.py @@ -260,6 +260,31 @@ def test_remove_explicit_value(self): self.assertEqual(service_dict['labels'], {'foo': '1', 'bar': ''}) +class MemoryOptionsTest(unittest.TestCase): + def test_validation_fails_with_just_memswap_limit(self): + """ + When you set a 'memswap_limit' it is invalid config unless you also set + a mem_limit + """ + with self.assertRaises(config.ConfigurationError): + make_service_dict( + 'foo', { + 'memswap_limit': 2000000, + }, + 'tests/' + ) + + def test_validation_with_correct_memswap_values(self): + service_dict = make_service_dict( + 'foo', { + 'mem_limit': 1000000, + 'memswap_limit': 2000000, + }, + 'tests/' + ) + self.assertEqual(service_dict['memswap_limit'], 2000000) + + class EnvTest(unittest.TestCase): def test_parse_environment_as_list(self): environment = [ diff --git a/tests/unit/service_test.py b/tests/unit/service_test.py index 0327874c145..d369371507c 100644 --- a/tests/unit/service_test.py +++ b/tests/unit/service_test.py @@ -155,6 +155,13 @@ def test_split_domainname_none(self): self.assertEqual(opts['hostname'], 'name', 'hostname') self.assertFalse('domainname' in opts, 'domainname') + def test_memory_swap_limit(self): + service = Service(name='foo', image='foo', hostname='name', client=self.mock_client, mem_limit=1000000000, memswap_limit=2000000000) + self.mock_client.containers.return_value = [] + opts = service._get_container_create_options({'some': 'overrides'}, 1) + self.assertEqual(opts['memswap_limit'], 2000000000) + self.assertEqual(opts['mem_limit'], 1000000000) + def test_split_domainname_fqdn(self): service = Service( 'foo',