Browse Source

Only attach services we'll read logs from in up

When 'up' is run with explicit list of services, compose will
start them together with their dependencies. It will attach to all
started services, but won't read output from dependencies (their
logs are not printed by 'up') - so the receive buffer of
dependencies will fill and at some point will start blocking those
services. Fix that by only attaching to services given in the
list.
To do that, move logic of choosing which services to attach from
cli/main.py to utils.py and use it from project.py to decide if
service should be attached.

Fixes #6018

Signed-off-by: Daniil Sigalov <[email protected]>
Daniil Sigalov 4 years ago
parent
commit
1b5278f977
3 changed files with 31 additions and 9 deletions
  1. 7 7
      compose/cli/main.py
  2. 9 2
      compose/project.py
  3. 15 0
      compose/utils.py

+ 7 - 7
compose/cli/main.py

@@ -38,6 +38,7 @@ from ..service import ConvergenceStrategy
 from ..service import ImageType
 from ..service import NeedsBuildError
 from ..service import OperationFailedError
+from ..utils import filter_attached_for_up
 from .command import get_config_from_options
 from .command import get_project_dir
 from .command import project_from_options
@@ -1071,6 +1072,7 @@ class TopLevelCommand:
                     renew_anonymous_volumes=options.get('--renew-anon-volumes'),
                     silent=options.get('--quiet-pull'),
                     cli=native_builder,
+                    attach_dependencies=attach_dependencies,
                 )
 
             try:
@@ -1401,13 +1403,11 @@ def log_printer_from_project(
 
 
 def filter_attached_containers(containers, service_names, attach_dependencies=False):
-    if attach_dependencies or not service_names:
-        return containers
-
-    return [
-        container
-        for container in containers if container.service in service_names
-    ]
+    return filter_attached_for_up(
+        containers,
+        service_names,
+        attach_dependencies,
+        lambda container: container.service)
 
 
 @contextlib.contextmanager

+ 9 - 2
compose/project.py

@@ -39,6 +39,7 @@ from .service import Service
 from .service import ServiceIpcMode
 from .service import ServiceNetworkMode
 from .service import ServicePidMode
+from .utils import filter_attached_for_up
 from .utils import microseconds_from_time_nano
 from .utils import truncate_string
 from .volume import ProjectVolumes
@@ -645,6 +646,7 @@ class Project:
            silent=False,
            cli=False,
            one_off=False,
+           attach_dependencies=False,
            override_options=None,
            ):
 
@@ -671,12 +673,17 @@ class Project:
             one_off=service_names if one_off else [],
         )
 
-        def do(service):
+        services_to_attach = filter_attached_for_up(
+            services,
+            service_names,
+            attach_dependencies,
+            lambda service: service.name)
 
+        def do(service):
             return service.execute_convergence_plan(
                 plans[service.name],
                 timeout=timeout,
-                detached=detached,
+                detached=detached or (service not in services_to_attach),
                 scale_override=scale_override.get(service.name),
                 rescale=rescale,
                 start=start,

+ 15 - 0
compose/utils.py

@@ -174,3 +174,18 @@ def truncate_string(s, max_chars=35):
     if len(s) > max_chars:
         return s[:max_chars - 2] + '...'
     return s
+
+
+def filter_attached_for_up(items, service_names, attach_dependencies=False,
+                           item_to_service_name=lambda x: x):
+    """This function contains the logic of choosing which services to
+    attach when doing docker-compose up. It may be used both with containers
+    and services, and any other entities that map to service names -
+    this mapping is provided by item_to_service_name."""
+    if attach_dependencies or not service_names:
+        return items
+
+    return [
+        item
+        for item in items if item_to_service_name(item) in service_names
+    ]