Merge branch 'TheClimateCorporation-forward-exit'

This commit is contained in:
Joffrey F 2017-03-01 18:23:52 -08:00
commit 31b2d9176b
4 changed files with 63 additions and 7 deletions

View File

@ -858,8 +858,11 @@ class TopLevelCommand(object):
running. (default: 10) running. (default: 10)
--remove-orphans Remove containers for services not --remove-orphans Remove containers for services not
defined in the Compose file defined in the Compose file
--exit-code-from SERVICE Return the exit code of the selected service container.
Requires --abort-on-container-exit.
""" """
start_deps = not options['--no-deps'] start_deps = not options['--no-deps']
exit_value_from = exitval_from_opts(options, self.project)
cascade_stop = options['--abort-on-container-exit'] cascade_stop = options['--abort-on-container-exit']
service_names = options['SERVICE'] service_names = options['SERVICE']
timeout = timeout_from_opts(options) timeout = timeout_from_opts(options)
@ -882,9 +885,11 @@ class TopLevelCommand(object):
if detached: if detached:
return return
attached_containers = filter_containers_to_service_names(to_attach, service_names)
log_printer = log_printer_from_project( log_printer = log_printer_from_project(
self.project, self.project,
filter_containers_to_service_names(to_attach, service_names), attached_containers,
options['--no-color'], options['--no-color'],
{'follow': True}, {'follow': True},
cascade_stop, cascade_stop,
@ -894,12 +899,34 @@ class TopLevelCommand(object):
if cascade_stop: if cascade_stop:
print("Aborting on container exit...") print("Aborting on container exit...")
exit_code = 0 exit_code = 0
for e in self.project.containers(service_names=options['SERVICE'], stopped=True): if exit_value_from:
if (not e.is_running and cascade_starter == e.name): candidates = filter(
if not e.exit_code == 0: lambda c: c.service == exit_value_from,
exit_code = e.exit_code attached_containers)
break if not candidates:
log.error(
'No containers matching the spec "{0}" '
'were run.'.format(exit_value_from)
)
exit_code = 2
elif len(candidates) > 1:
exit_values = filter(
lambda e: e != 0,
[c.inspect()['State']['ExitCode'] for c in candidates]
)
exit_code = exit_values[0]
else:
exit_code = candidates[0].inspect()['State']['ExitCode']
else:
for e in self.project.containers(service_names=options['SERVICE'], stopped=True):
if (not e.is_running and cascade_starter == e.name):
if not e.exit_code == 0:
exit_code = e.exit_code
break
self.project.stop(service_names=service_names, timeout=timeout) self.project.stop(service_names=service_names, timeout=timeout)
sys.exit(exit_code) sys.exit(exit_code)
@ -939,6 +966,19 @@ def timeout_from_opts(options):
return None if timeout is None else int(timeout) return None if timeout is None else int(timeout)
def exitval_from_opts(options, project):
exit_value_from = options.get('--exit-code-from')
if exit_value_from:
if not options.get('--abort-on-container-exit'):
log.warn('using --exit-code-from implies --abort-on-container-exit')
options['--abort-on-container-exit'] = True
if exit_value_from not in [s.name for s in project.get_services()]:
log.error('No service named "%s" was found in your compose file.',
exit_value_from)
sys.exit(2)
return exit_value_from
def image_type_from_opt(flag, value): def image_type_from_opt(flag, value):
if not value: if not value:
return ImageType.none return ImageType.none

View File

@ -467,7 +467,7 @@ _docker_compose_up() {
case "$cur" in case "$cur" in
-*) -*)
COMPREPLY=( $( compgen -W "--abort-on-container-exit --build -d --force-recreate --help --no-build --no-color --no-deps --no-recreate --timeout -t --remove-orphans" -- "$cur" ) ) COMPREPLY=( $( compgen -W "--exit-code-from --abort-on-container-exit --build -d --force-recreate --help --no-build --no-color --no-deps --no-recreate --timeout -t --remove-orphans" -- "$cur" ) )
;; ;;
*) *)
__docker_compose_services_all __docker_compose_services_all

View File

@ -1976,3 +1976,13 @@ class CLITestCase(DockerClientTestCase):
self.dispatch(['up', '-d']) self.dispatch(['up', '-d'])
result = self.dispatch(['top']) result = self.dispatch(['top'])
assert result.stdout.count("top") == 4 assert result.stdout.count("top") == 4
def test_forward_exitval(self):
self.base_dir = 'tests/fixtures/exit-code-from'
proc = start_process(
self.base_dir,
['up', '--abort-on-container-exit', '--exit-code-from', 'another'])
result = wait_on_process(proc, returncode=1)
assert 'exitcodefrom_another_1 exited with code 1' in result.stdout

View File

@ -0,0 +1,6 @@
simple:
image: busybox:latest
command: sh -c "echo hello && tail -f /dev/null"
another:
image: busybox:latest
command: /bin/false