mirror of https://github.com/docker/compose.git
Merge pull request #2130 from scipetr/master
Add flag for stops all containers if any container was stopped.
This commit is contained in:
commit
d56f64c30a
|
@ -13,10 +13,11 @@ from compose.utils import split_buffer
|
|||
class LogPrinter(object):
|
||||
"""Print logs from many containers to a single output stream."""
|
||||
|
||||
def __init__(self, containers, output=sys.stdout, monochrome=False):
|
||||
def __init__(self, containers, output=sys.stdout, monochrome=False, cascade_stop=False):
|
||||
self.containers = containers
|
||||
self.output = utils.get_output_stream(output)
|
||||
self.monochrome = monochrome
|
||||
self.cascade_stop = cascade_stop
|
||||
|
||||
def run(self):
|
||||
if not self.containers:
|
||||
|
@ -24,7 +25,7 @@ class LogPrinter(object):
|
|||
|
||||
prefix_width = max_name_width(self.containers)
|
||||
generators = list(self._make_log_generators(self.monochrome, prefix_width))
|
||||
for line in Multiplexer(generators).loop():
|
||||
for line in Multiplexer(generators, cascade_stop=self.cascade_stop).loop():
|
||||
self.output.write(line)
|
||||
self.output.flush()
|
||||
|
||||
|
|
|
@ -590,25 +590,33 @@ class TopLevelCommand(DocoptCommand):
|
|||
Usage: up [options] [SERVICE...]
|
||||
|
||||
Options:
|
||||
-d Detached mode: Run containers in the background,
|
||||
print new container names.
|
||||
--no-color Produce monochrome output.
|
||||
--no-deps Don't start linked services.
|
||||
--force-recreate Recreate containers even if their configuration and
|
||||
image haven't changed. Incompatible with --no-recreate.
|
||||
--no-recreate If containers already exist, don't recreate them.
|
||||
Incompatible with --force-recreate.
|
||||
--no-build Don't build an image, even if it's missing
|
||||
-t, --timeout TIMEOUT Use this timeout in seconds for container shutdown
|
||||
when attached or when containers are already
|
||||
running. (default: 10)
|
||||
-d Detached mode: Run containers in the background,
|
||||
print new container names.
|
||||
Incompatible with --abort-on-container-exit.
|
||||
--no-color Produce monochrome output.
|
||||
--no-deps Don't start linked services.
|
||||
--force-recreate Recreate containers even if their configuration
|
||||
and image haven't changed.
|
||||
Incompatible with --no-recreate.
|
||||
--no-recreate If containers already exist, don't recreate them.
|
||||
Incompatible with --force-recreate.
|
||||
--no-build Don't build an image, even if it's missing
|
||||
--abort-on-container-exit Stops all containers if any container was stopped.
|
||||
Incompatible with -d.
|
||||
-t, --timeout TIMEOUT Use this timeout in seconds for container shutdown
|
||||
when attached or when containers are already
|
||||
running. (default: 10)
|
||||
"""
|
||||
monochrome = options['--no-color']
|
||||
start_deps = not options['--no-deps']
|
||||
cascade_stop = options['--abort-on-container-exit']
|
||||
service_names = options['SERVICE']
|
||||
timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
|
||||
detached = options.get('-d')
|
||||
|
||||
if detached and cascade_stop:
|
||||
raise UserError("--abort-on-container-exit and -d cannot be combined.")
|
||||
|
||||
to_attach = project.up(
|
||||
service_names=service_names,
|
||||
start_deps=start_deps,
|
||||
|
@ -619,7 +627,7 @@ class TopLevelCommand(DocoptCommand):
|
|||
)
|
||||
|
||||
if not detached:
|
||||
log_printer = build_log_printer(to_attach, service_names, monochrome)
|
||||
log_printer = build_log_printer(to_attach, service_names, monochrome, cascade_stop)
|
||||
attach_to_logs(project, log_printer, service_names, timeout)
|
||||
|
||||
def version(self, project, options):
|
||||
|
@ -695,13 +703,13 @@ def run_one_off_container(container_options, project, service, options):
|
|||
sys.exit(exit_code)
|
||||
|
||||
|
||||
def build_log_printer(containers, service_names, monochrome):
|
||||
def build_log_printer(containers, service_names, monochrome, cascade_stop):
|
||||
if service_names:
|
||||
containers = [
|
||||
container
|
||||
for container in containers if container.service in service_names
|
||||
]
|
||||
return LogPrinter(containers, monochrome=monochrome)
|
||||
return LogPrinter(containers, monochrome=monochrome, cascade_stop=cascade_stop)
|
||||
|
||||
|
||||
def attach_to_logs(project, log_printer, service_names, timeout):
|
||||
|
|
|
@ -20,8 +20,9 @@ class Multiplexer(object):
|
|||
parallel and yielding results as they come in.
|
||||
"""
|
||||
|
||||
def __init__(self, iterators):
|
||||
def __init__(self, iterators, cascade_stop=False):
|
||||
self.iterators = iterators
|
||||
self.cascade_stop = cascade_stop
|
||||
self._num_running = len(iterators)
|
||||
self.queue = Queue()
|
||||
|
||||
|
@ -36,7 +37,10 @@ class Multiplexer(object):
|
|||
raise exception
|
||||
|
||||
if item is STOP:
|
||||
self._num_running -= 1
|
||||
if self.cascade_stop is True:
|
||||
break
|
||||
else:
|
||||
self._num_running -= 1
|
||||
else:
|
||||
yield item
|
||||
except Empty:
|
||||
|
|
|
@ -15,18 +15,22 @@ parent = "smn_compose_cli"
|
|||
Usage: up [options] [SERVICE...]
|
||||
|
||||
Options:
|
||||
-d Detached mode: Run containers in the background,
|
||||
print new container names.
|
||||
--no-color Produce monochrome output.
|
||||
--no-deps Don't start linked services.
|
||||
--force-recreate Recreate containers even if their configuration and
|
||||
image haven't changed. Incompatible with --no-recreate.
|
||||
--no-recreate If containers already exist, don't recreate them.
|
||||
Incompatible with --force-recreate.
|
||||
--no-build Don't build an image, even if it's missing
|
||||
-t, --timeout TIMEOUT Use this timeout in seconds for container shutdown
|
||||
when attached or when containers are already
|
||||
running. (default: 10)
|
||||
-d Detached mode: Run containers in the background,
|
||||
print new container names.
|
||||
Incompatible with --abort-on-container-exit.
|
||||
--no-color Produce monochrome output.
|
||||
--no-deps Don't start linked services.
|
||||
--force-recreate Recreate containers even if their configuration
|
||||
and image haven't changed.
|
||||
Incompatible with --no-recreate.
|
||||
--no-recreate If containers already exist, don't recreate them.
|
||||
Incompatible with --force-recreate.
|
||||
--no-build Don't build an image, even if it's missing
|
||||
--abort-on-container-exit Stops all containers if any container was stopped.
|
||||
Incompatible with -d.
|
||||
-t, --timeout TIMEOUT Use this timeout in seconds for container shutdown
|
||||
when attached or when containers are already
|
||||
running. (default: 10)
|
||||
```
|
||||
|
||||
Builds, (re)creates, starts, and attaches to containers for a service.
|
||||
|
|
|
@ -36,7 +36,7 @@ class CLIMainTestCase(unittest.TestCase):
|
|||
mock_container('another', 1),
|
||||
]
|
||||
service_names = ['web', 'db']
|
||||
log_printer = build_log_printer(containers, service_names, True)
|
||||
log_printer = build_log_printer(containers, service_names, True, False)
|
||||
self.assertEqual(log_printer.containers, containers[:3])
|
||||
|
||||
def test_build_log_printer_all_services(self):
|
||||
|
@ -46,7 +46,7 @@ class CLIMainTestCase(unittest.TestCase):
|
|||
mock_container('other', 1),
|
||||
]
|
||||
service_names = []
|
||||
log_printer = build_log_printer(containers, service_names, True)
|
||||
log_printer = build_log_printer(containers, service_names, True, False)
|
||||
self.assertEqual(log_printer.containers, containers)
|
||||
|
||||
def test_attach_to_logs(self):
|
||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import absolute_import
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
from time import sleep
|
||||
|
||||
from compose.cli.multiplexer import Multiplexer
|
||||
|
||||
|
@ -46,3 +47,20 @@ class MultiplexerTest(unittest.TestCase):
|
|||
|
||||
with self.assertRaises(Problem):
|
||||
list(mux.loop())
|
||||
|
||||
def test_cascade_stop(self):
|
||||
mux = Multiplexer([
|
||||
((lambda x: sleep(0.01) or x)(x) for x in ['after 0.01 sec T1',
|
||||
'after 0.02 sec T1',
|
||||
'after 0.03 sec T1']),
|
||||
((lambda x: sleep(0.02) or x)(x) for x in ['after 0.02 sec T2',
|
||||
'after 0.04 sec T2',
|
||||
'after 0.06 sec T2']),
|
||||
], cascade_stop=True)
|
||||
|
||||
self.assertEqual(
|
||||
['after 0.01 sec T1',
|
||||
'after 0.02 sec T1',
|
||||
'after 0.02 sec T2',
|
||||
'after 0.03 sec T1'],
|
||||
sorted(list(mux.loop())))
|
||||
|
|
Loading…
Reference in New Issue