Browse Source

Don't attempt iterating on None during parallel pull

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 7 năm trước cách đây
mục cha
commit
90625cf31b
3 tập tin đã thay đổi với 28 bổ sung6 xóa
  1. 5 6
      compose/project.py
  2. 6 0
      compose/utils.py
  3. 17 0
      tests/integration/project_test.py

+ 5 - 6
compose/project.py

@@ -34,6 +34,7 @@ from .service import Service
 from .service import ServiceNetworkMode
 from .service import ServicePidMode
 from .utils import microseconds_from_time_nano
+from .utils import truncate_string
 from .volume import ProjectVolumes
 
 
@@ -554,12 +555,10 @@ class Project(object):
         if parallel_pull:
             def pull_service(service):
                 strm = service.pull(ignore_pull_failures, True, stream=True)
-                writer = parallel.get_stream_writer()
+                if strm is None:  # Attempting to pull service with no `image` key is a no-op
+                    return
 
-                def trunc(s):
-                    if len(s) > 35:
-                        return s[:33] + '...'
-                    return s
+                writer = parallel.get_stream_writer()
 
                 for event in strm:
                     if 'status' not in event:
@@ -572,7 +571,7 @@ class Project(object):
                             status = '{} ({:.1%})'.format(status, percentage)
 
                     writer.write(
-                        msg, service.name, trunc(status), lambda s: s
+                        msg, service.name, truncate_string(status), lambda s: s
                     )
 
             _, errors = parallel.parallel_execute(

+ 6 - 0
compose/utils.py

@@ -180,3 +180,9 @@ def unique_everseen(iterable, key=lambda x: x):
         if unique_key not in seen:
             seen.add(unique_key)
             yield element
+
+
+def truncate_string(s, max_chars=35):
+    if len(s) > max_chars:
+        return s[:max_chars - 2] + '...'
+    return s

+ 17 - 0
tests/integration/project_test.py

@@ -105,6 +105,23 @@ class ProjectTest(DockerClientTestCase):
         project = Project('composetest', [web, db], self.client)
         assert set(project.containers(stopped=True)) == set([web_1, db_1])
 
+    def test_parallel_pull_with_no_image(self):
+        config_data = build_config(
+            version=V2_3,
+            services=[{
+                'name': 'web',
+                'build': {'context': '.'},
+            }],
+        )
+
+        project = Project.from_config(
+            name='composetest',
+            config_data=config_data,
+            client=self.client
+        )
+
+        project.pull(parallel_pull=True)
+
     def test_volumes_from_service(self):
         project = Project.from_config(
             name='composetest',