Browse Source

Resolves #1856, fix regression in #1645. Includes some refactoring to make testing easier.

Signed-off-by: Daniel Nephin <[email protected]>
Daniel Nephin 10 years ago
parent
commit
3a0153859a
3 changed files with 75 additions and 14 deletions
  1. 23 13
      compose/cli/main.py
  2. 5 1
      compose/container.py
  3. 47 0
      tests/unit/cli/main_test.py

+ 23 - 13
compose/cli/main.py

@@ -538,19 +538,8 @@ class TopLevelCommand(Command):
         )
 
         if not detached:
-            print("Attaching to", list_containers(to_attach))
-            log_printer = LogPrinter(to_attach, attach_params={"logs": True}, monochrome=monochrome)
-
-            try:
-                log_printer.run()
-            finally:
-                def handler(signal, frame):
-                    project.kill(service_names=service_names)
-                    sys.exit(0)
-                signal.signal(signal.SIGINT, handler)
-
-                print("Gracefully stopping... (press Ctrl+C again to force)")
-                project.stop(service_names=service_names, timeout=timeout)
+            log_printer = build_log_printer(to_attach, service_names, monochrome)
+            attach_to_logs(project, log_printer, service_names, timeout)
 
     def migrate_to_labels(self, project, _options):
         """
@@ -593,5 +582,26 @@ class TopLevelCommand(Command):
             print(get_version_info('full'))
 
 
+def build_log_printer(containers, service_names, monochrome):
+    return LogPrinter(
+        [c for c in containers if c.service in service_names],
+        attach_params={"logs": True},
+        monochrome=monochrome)
+
+
+def attach_to_logs(project, log_printer, service_names, timeout):
+    print("Attaching to", list_containers(log_printer.containers))
+    try:
+        log_printer.run()
+    finally:
+        def handler(signal, frame):
+            project.kill(service_names=service_names)
+            sys.exit(0)
+        signal.signal(signal.SIGINT, handler)
+
+        print("Gracefully stopping... (press Ctrl+C again to force)")
+        project.stop(service_names=service_names, timeout=timeout)
+
+
 def list_containers(containers):
     return ", ".join(c.name for c in containers)

+ 5 - 1
compose/container.py

@@ -64,9 +64,13 @@ class Container(object):
     def name(self):
         return self.dictionary['Name'][1:]
 
+    @property
+    def service(self):
+        return self.labels.get(LABEL_SERVICE)
+
     @property
     def name_without_project(self):
-        return '{0}_{1}'.format(self.labels.get(LABEL_SERVICE), self.number)
+        return '{0}_{1}'.format(self.service, self.number)
 
     @property
     def number(self):

+ 47 - 0
tests/unit/cli/main_test.py

@@ -0,0 +1,47 @@
+from __future__ import absolute_import
+
+from compose import container
+from compose.cli.log_printer import LogPrinter
+from compose.cli.main import attach_to_logs
+from compose.cli.main import build_log_printer
+from compose.project import Project
+from tests import mock
+from tests import unittest
+
+
+def mock_container(service, number):
+    return mock.create_autospec(
+        container.Container,
+        service=service,
+        number=number,
+        name_without_project='{0}_{1}'.format(service, number))
+
+
+class CLIMainTestCase(unittest.TestCase):
+
+    def test_build_log_printer(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']
+        log_printer = build_log_printer(containers, service_names, True)
+        self.assertEqual(log_printer.containers, containers[:3])
+
+    def test_attach_to_logs(self):
+        project = mock.create_autospec(Project)
+        log_printer = mock.create_autospec(LogPrinter, containers=[])
+        service_names = ['web', 'db']
+        timeout = 12
+
+        with mock.patch('compose.cli.main.signal', autospec=True) as mock_signal:
+            attach_to_logs(project, log_printer, service_names, timeout)
+
+        mock_signal.signal.assert_called_once_with(mock_signal.SIGINT, mock.ANY)
+        log_printer.run.assert_called_once_with()
+        project.stop.assert_called_once_with(
+            service_names=service_names,
+            timeout=timeout)