diff --git a/paunch/builder/compose1.py b/paunch/builder/compose1.py index b573a49..3b27bee 100644 --- a/paunch/builder/compose1.py +++ b/paunch/builder/compose1.py @@ -13,6 +13,7 @@ import json import logging +import re import tenacity LOG = logging.getLogger(__name__) @@ -134,9 +135,13 @@ class ComposeV1Builder(object): if cconfig.get(key, False): cmd.append(arg) - def string_arg(self, cconfig, cmd, key, arg): + def string_arg(self, cconfig, cmd, key, arg, transform=None): if key in cconfig: - cmd.append('%s=%s' % (arg, cconfig[key])) + if transform: + value = transform(cconfig[key]) + else: + value = cconfig[key] + cmd.append('%s=%s' % (arg, value)) def list_or_string_arg(self, cconfig, cmd, key, arg): if key not in cconfig: @@ -187,8 +192,11 @@ class ComposeV1Builder(object): cmd.append('--health-timeout=%s' % hconfig['timeout']) if 'retries' in hconfig: cmd.append('--health-retries=%s' % hconfig['retries']) - if 'privileged' in cconfig: - cmd.append('--privileged=%s' % str(cconfig['privileged']).lower()) + + def lower(a): + return str(a).lower() + + self.string_arg(cconfig, cmd, 'privileged', '--privileged', lower) self.string_arg(cconfig, cmd, 'restart', '--restart') self.string_arg(cconfig, cmd, 'user', '--user') self.list_arg(cconfig, cmd, 'volumes', '--volume') @@ -198,6 +206,42 @@ class ComposeV1Builder(object): cmd.append('--log-opt=tag=%s' % cconfig['log_tag']) self.string_arg(cconfig, cmd, 'cpu_shares', '--cpu-shares') self.string_arg(cconfig, cmd, 'security_opt', '--security-opt') + self.string_arg(cconfig, cmd, 'stop_signal', '--stop-signal') + + def duration(a): + if isinstance(a, (int, long, float)): + return a + + # match groups of the format 5h34m56s + m = re.match('^' + '(([\d\.]+)h)?' + '(([\d\.]+)m)?' + '(([\d\.]+)s)?' + '(([\d\.]+)ms)?' + '(([\d\.]+)us)?' + '$', a) + + if not m: + # fallback to parsing string as a number + return float(a) + + n = 0.0 + if m.group(2): + n += 3600 * float(m.group(2)) + if m.group(4): + n += 60 * float(m.group(4)) + if m.group(6): + n += float(m.group(6)) + if m.group(8): + n += float(m.group(8)) / 1000.0 + if m.group(10): + n += float(m.group(10)) / 1000000.0 + return n + + self.string_arg(cconfig, cmd, + 'stop_grace_period', '--stop-timeout', + duration) + # TODO(sbaker): add missing compose v1 properties: # cap_add, cap_drop # cgroup_parent diff --git a/paunch/tests/test_builder_compose1.py b/paunch/tests/test_builder_compose1.py index 92aa533..792d97d 100644 --- a/paunch/tests/test_builder_compose1.py +++ b/paunch/tests/test_builder_compose1.py @@ -440,6 +440,37 @@ three-12345678 three''', '', 0), cmd ) + def test_durations(self): + config = { + 'a': {'stop_grace_period': 123}, + 'b': {'stop_grace_period': 123.5}, + 'c': {'stop_grace_period': '123.3'}, + 'd': {'stop_grace_period': '2.5s'}, + 'e': {'stop_grace_period': '10s'}, + 'f': {'stop_grace_period': '1m30s'}, + 'g': {'stop_grace_period': '2h32m'}, + 'h': {'stop_grace_period': '5h34m56s'}, + 'i': {'stop_grace_period': '1h1m1s1ms1us'}, + } + builder = compose1.ComposeV1Builder('foo', config, None) + + result = { + 'a': '--stop-timeout=123', + 'b': '--stop-timeout=123.5', + 'c': '--stop-timeout=123.3', + 'd': '--stop-timeout=2.5', + 'e': '--stop-timeout=10.0', + 'f': '--stop-timeout=90.0', + 'g': '--stop-timeout=9120.0', + 'h': '--stop-timeout=20096.0', + 'i': '--stop-timeout=3661.001001', + } + + for container, arg in result.items(): + cmd = [] + builder.docker_run_args(cmd, container) + self.assertIn(arg, cmd) + def test_docker_run_args_lists(self): config = { 'one': {