mirror of https://github.com/docker/compose.git
Merge pull request #6950 from benthorner/master
Add "--attach-dependencies" to command "up" for attaching to dependencies
This commit is contained in:
commit
f0e5926ea7
|
@ -1012,6 +1012,7 @@ class TopLevelCommand(object):
|
||||||
--build Build images before starting containers.
|
--build Build images before starting containers.
|
||||||
--abort-on-container-exit Stops all containers if any container was
|
--abort-on-container-exit Stops all containers if any container was
|
||||||
stopped. Incompatible with -d.
|
stopped. Incompatible with -d.
|
||||||
|
--attach-dependencies Attach to dependent containers
|
||||||
-t, --timeout TIMEOUT Use this timeout in seconds for container
|
-t, --timeout TIMEOUT Use this timeout in seconds for container
|
||||||
shutdown when attached or when containers are
|
shutdown when attached or when containers are
|
||||||
already running. (default: 10)
|
already running. (default: 10)
|
||||||
|
@ -1033,16 +1034,18 @@ class TopLevelCommand(object):
|
||||||
remove_orphans = options['--remove-orphans']
|
remove_orphans = options['--remove-orphans']
|
||||||
detached = options.get('--detach')
|
detached = options.get('--detach')
|
||||||
no_start = options.get('--no-start')
|
no_start = options.get('--no-start')
|
||||||
|
attach_dependencies = options.get('--attach-dependencies')
|
||||||
|
|
||||||
if detached and (cascade_stop or exit_value_from):
|
if detached and (cascade_stop or exit_value_from or attach_dependencies):
|
||||||
raise UserError("--abort-on-container-exit and -d cannot be combined.")
|
raise UserError(
|
||||||
|
"-d cannot be combined with --abort-on-container-exit or --attach-dependencies.")
|
||||||
|
|
||||||
ignore_orphans = self.toplevel_environment.get_boolean('COMPOSE_IGNORE_ORPHANS')
|
ignore_orphans = self.toplevel_environment.get_boolean('COMPOSE_IGNORE_ORPHANS')
|
||||||
|
|
||||||
if ignore_orphans and remove_orphans:
|
if ignore_orphans and remove_orphans:
|
||||||
raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.")
|
raise UserError("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined.")
|
||||||
|
|
||||||
opts = ['--detach', '--abort-on-container-exit', '--exit-code-from']
|
opts = ['--detach', '--abort-on-container-exit', '--exit-code-from', '--attach-dependencies']
|
||||||
for excluded in [x for x in opts if options.get(x) and no_start]:
|
for excluded in [x for x in opts if options.get(x) and no_start]:
|
||||||
raise UserError('--no-start and {} cannot be combined.'.format(excluded))
|
raise UserError('--no-start and {} cannot be combined.'.format(excluded))
|
||||||
|
|
||||||
|
@ -1087,7 +1090,10 @@ class TopLevelCommand(object):
|
||||||
if detached or no_start:
|
if detached or no_start:
|
||||||
return
|
return
|
||||||
|
|
||||||
attached_containers = filter_containers_to_service_names(to_attach, service_names)
|
attached_containers = filter_attached_containers(
|
||||||
|
to_attach,
|
||||||
|
service_names,
|
||||||
|
attach_dependencies)
|
||||||
|
|
||||||
log_printer = log_printer_from_project(
|
log_printer = log_printer_from_project(
|
||||||
self.project,
|
self.project,
|
||||||
|
@ -1392,8 +1398,8 @@ def log_printer_from_project(
|
||||||
log_args=log_args)
|
log_args=log_args)
|
||||||
|
|
||||||
|
|
||||||
def filter_containers_to_service_names(containers, service_names):
|
def filter_attached_containers(containers, service_names, attach_dependencies=False):
|
||||||
if not service_names:
|
if attach_dependencies or not service_names:
|
||||||
return containers
|
return containers
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -545,7 +545,7 @@ _docker_compose_up() {
|
||||||
|
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W "--abort-on-container-exit --always-recreate-deps --build -d --detach --exit-code-from --force-recreate --help --no-build --no-color --no-deps --no-recreate --no-start --renew-anon-volumes -V --remove-orphans --scale --timeout -t" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "--abort-on-container-exit --always-recreate-deps --attach-dependencies --build -d --detach --exit-code-from --force-recreate --help --no-build --no-color --no-deps --no-recreate --no-start --renew-anon-volumes -V --remove-orphans --scale --timeout -t" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
__docker_compose_complete_services
|
__docker_compose_complete_services
|
||||||
|
|
|
@ -284,7 +284,7 @@ __docker-compose_subcommand() {
|
||||||
(up)
|
(up)
|
||||||
_arguments \
|
_arguments \
|
||||||
$opts_help \
|
$opts_help \
|
||||||
'(--abort-on-container-exit)-d[Detached mode: Run containers in the background, print new container names. Incompatible with --abort-on-container-exit.]' \
|
'(--abort-on-container-exit)-d[Detached mode: Run containers in the background, print new container names. Incompatible with --abort-on-container-exit and --attach-dependencies.]' \
|
||||||
$opts_no_color \
|
$opts_no_color \
|
||||||
$opts_no_deps \
|
$opts_no_deps \
|
||||||
$opts_force_recreate \
|
$opts_force_recreate \
|
||||||
|
@ -292,6 +292,7 @@ __docker-compose_subcommand() {
|
||||||
$opts_no_build \
|
$opts_no_build \
|
||||||
"(--no-build)--build[Build images before starting containers.]" \
|
"(--no-build)--build[Build images before starting containers.]" \
|
||||||
"(-d)--abort-on-container-exit[Stops all containers if any container was stopped. Incompatible with -d.]" \
|
"(-d)--abort-on-container-exit[Stops all containers if any container was stopped. Incompatible with -d.]" \
|
||||||
|
"(-d)--attach-dependencies[Attach to dependent containers. Incompatible with -d.]" \
|
||||||
'(-t --timeout)'{-t,--timeout}"[Use this timeout in seconds for container shutdown when attached or when containers are already running. (default: 10)]:seconds: " \
|
'(-t --timeout)'{-t,--timeout}"[Use this timeout in seconds for container shutdown when attached or when containers are already running. (default: 10)]:seconds: " \
|
||||||
'--scale[SERVICE=NUM Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.]:service scale SERVICE=NUM: ' \
|
'--scale[SERVICE=NUM Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.]:service scale SERVICE=NUM: ' \
|
||||||
'--exit-code-from=[Return the exit code of the selected service container. Implies --abort-on-container-exit]:service:__docker-compose_services' \
|
'--exit-code-from=[Return the exit code of the selected service container. Implies --abort-on-container-exit]:service:__docker-compose_services' \
|
||||||
|
|
|
@ -1571,6 +1571,26 @@ services:
|
||||||
assert len(db.containers()) == 0
|
assert len(db.containers()) == 0
|
||||||
assert len(console.containers()) == 0
|
assert len(console.containers()) == 0
|
||||||
|
|
||||||
|
def test_up_with_attach_dependencies(self):
|
||||||
|
self.base_dir = 'tests/fixtures/echo-services-dependencies'
|
||||||
|
result = self.dispatch(['up', '--attach-dependencies', '--no-color', 'simple'], None)
|
||||||
|
simple_name = self.project.get_service('simple').containers(stopped=True)[0].name_without_project
|
||||||
|
another_name = self.project.get_service('another').containers(
|
||||||
|
stopped=True
|
||||||
|
)[0].name_without_project
|
||||||
|
|
||||||
|
assert '{} | simple'.format(simple_name) in result.stdout
|
||||||
|
assert '{} | another'.format(another_name) in result.stdout
|
||||||
|
|
||||||
|
def test_up_handles_aborted_dependencies(self):
|
||||||
|
self.base_dir = 'tests/fixtures/abort-on-container-exit-dependencies'
|
||||||
|
proc = start_process(
|
||||||
|
self.base_dir,
|
||||||
|
['up', 'simple', '--attach-dependencies', '--abort-on-container-exit'])
|
||||||
|
wait_on_condition(ContainerCountCondition(self.project, 0))
|
||||||
|
proc.wait()
|
||||||
|
assert proc.returncode == 1
|
||||||
|
|
||||||
def test_up_with_force_recreate(self):
|
def test_up_with_force_recreate(self):
|
||||||
self.dispatch(['up', '-d'], None)
|
self.dispatch(['up', '-d'], None)
|
||||||
service = self.project.get_service('simple')
|
service = self.project.get_service('simple')
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
version: "2.0"
|
||||||
|
services:
|
||||||
|
simple:
|
||||||
|
image: busybox:1.31.0-uclibc
|
||||||
|
command: top
|
||||||
|
depends_on:
|
||||||
|
- another
|
||||||
|
another:
|
||||||
|
image: busybox:1.31.0-uclibc
|
||||||
|
command: ls /thecakeisalie
|
|
@ -0,0 +1,10 @@
|
||||||
|
version: "2.0"
|
||||||
|
services:
|
||||||
|
simple:
|
||||||
|
image: busybox:1.31.0-uclibc
|
||||||
|
command: echo simple
|
||||||
|
depends_on:
|
||||||
|
- another
|
||||||
|
another:
|
||||||
|
image: busybox:1.31.0-uclibc
|
||||||
|
command: echo another
|
|
@ -12,7 +12,7 @@ from compose.cli.formatter import ConsoleWarningFormatter
|
||||||
from compose.cli.main import build_one_off_container_options
|
from compose.cli.main import build_one_off_container_options
|
||||||
from compose.cli.main import call_docker
|
from compose.cli.main import call_docker
|
||||||
from compose.cli.main import convergence_strategy_from_opts
|
from compose.cli.main import convergence_strategy_from_opts
|
||||||
from compose.cli.main import filter_containers_to_service_names
|
from compose.cli.main import filter_attached_containers
|
||||||
from compose.cli.main import get_docker_start_call
|
from compose.cli.main import get_docker_start_call
|
||||||
from compose.cli.main import setup_console_handler
|
from compose.cli.main import setup_console_handler
|
||||||
from compose.cli.main import warn_for_swarm_mode
|
from compose.cli.main import warn_for_swarm_mode
|
||||||
|
@ -37,7 +37,7 @@ def logging_handler():
|
||||||
|
|
||||||
class TestCLIMainTestCase(object):
|
class TestCLIMainTestCase(object):
|
||||||
|
|
||||||
def test_filter_containers_to_service_names(self):
|
def test_filter_attached_containers(self):
|
||||||
containers = [
|
containers = [
|
||||||
mock_container('web', 1),
|
mock_container('web', 1),
|
||||||
mock_container('web', 2),
|
mock_container('web', 2),
|
||||||
|
@ -46,17 +46,29 @@ class TestCLIMainTestCase(object):
|
||||||
mock_container('another', 1),
|
mock_container('another', 1),
|
||||||
]
|
]
|
||||||
service_names = ['web', 'db']
|
service_names = ['web', 'db']
|
||||||
actual = filter_containers_to_service_names(containers, service_names)
|
actual = filter_attached_containers(containers, service_names)
|
||||||
assert actual == containers[:3]
|
assert actual == containers[:3]
|
||||||
|
|
||||||
def test_filter_containers_to_service_names_all(self):
|
def test_filter_attached_containers_with_dependencies(self):
|
||||||
|
containers = [
|
||||||
|
mock_container('web', 1),
|
||||||
|
mock_container('web', 2),
|
||||||
|
mock_container('db', 1),
|
||||||
|
mock_container('other', 1),
|
||||||
|
mock_container('another', 1),
|
||||||
|
]
|
||||||
|
service_names = ['web', 'db']
|
||||||
|
actual = filter_attached_containers(containers, service_names, attach_dependencies=True)
|
||||||
|
assert actual == containers
|
||||||
|
|
||||||
|
def test_filter_attached_containers_all(self):
|
||||||
containers = [
|
containers = [
|
||||||
mock_container('web', 1),
|
mock_container('web', 1),
|
||||||
mock_container('db', 1),
|
mock_container('db', 1),
|
||||||
mock_container('other', 1),
|
mock_container('other', 1),
|
||||||
]
|
]
|
||||||
service_names = []
|
service_names = []
|
||||||
actual = filter_containers_to_service_names(containers, service_names)
|
actual = filter_attached_containers(containers, service_names)
|
||||||
assert actual == containers
|
assert actual == containers
|
||||||
|
|
||||||
def test_warning_in_swarm_mode(self):
|
def test_warning_in_swarm_mode(self):
|
||||||
|
|
Loading…
Reference in New Issue