浏览代码

Fix a bug in ExtendsResolver where the service name of the extended service was wrong.

This bug can be seen by the change to the test case. When the extended service
uses a different name, the error was reported incorrectly.

By fixing this bug we can simplify self.signature and self.detect_cycles to
always use self.service_name.

Signed-off-by: Daniel Nephin <[email protected]>
Daniel Nephin 10 年之前
父节点
当前提交
3a43110f06
共有 4 个文件被更改,包括 25 次插入22 次删除
  1. 11 9
      compose/config/config.py
  2. 1 1
      tests/fixtures/extends/circle-1.yml
  3. 1 1
      tests/fixtures/extends/circle-2.yml
  4. 12 11
      tests/unit/config/config_test.py

+ 11 - 9
compose/config/config.py

@@ -247,11 +247,17 @@ class ServiceExtendsResolver(object):
         self.service_name = service_name
         self.service_dict['name'] = service_name
 
-    def detect_cycle(self, name):
-        if self.signature(name) in self.already_seen:
-            raise CircularReference(self.already_seen + [self.signature(name)])
+    @property
+    def signature(self):
+        return self.filename, self.service_name
+
+    def detect_cycle(self):
+        if self.signature in self.already_seen:
+            raise CircularReference(self.already_seen + [self.signature])
 
     def run(self):
+        self.detect_cycle()
+
         service_dict = dict(self.service_dict)
         env = resolve_environment(self.working_dir, self.service_dict)
         if env:
@@ -284,12 +290,11 @@ class ServiceExtendsResolver(object):
         resolver = ServiceExtendsResolver(
             os.path.dirname(extended_config_path),
             extended_config_path,
-            self.service_name,
+            service_name,
             service_config,
-            already_seen=self.already_seen + [self.signature(self.service_name)],
+            already_seen=self.already_seen + [self.signature],
         )
 
-        resolver.detect_cycle(service_name)
         other_service_dict = process_service(resolver.working_dir, resolver.run())
         validate_extended_service_dict(
             other_service_dict,
@@ -309,9 +314,6 @@ class ServiceExtendsResolver(object):
             return expand_path(self.working_dir, extends_options['file'])
         return self.filename
 
-    def signature(self, name):
-        return self.filename, name
-
 
 def resolve_environment(working_dir, service_dict):
     """Unpack any environment variables from an env_file, if set.

+ 1 - 1
tests/fixtures/extends/circle-1.yml

@@ -5,7 +5,7 @@ bar:
 web:
   extends:
     file: circle-2.yml
-    service: web
+    service: other
 baz:
   image: busybox
 quux:

+ 1 - 1
tests/fixtures/extends/circle-2.yml

@@ -2,7 +2,7 @@ foo:
   image: busybox
 bar:
   image: busybox
-web:
+other:
   extends:
     file: circle-1.yml
     service: web

+ 12 - 11
tests/unit/config/config_test.py

@@ -1080,18 +1080,19 @@ class ExtendsTest(unittest.TestCase):
         ]))
 
     def test_circular(self):
-        try:
+        with pytest.raises(config.CircularReference) as exc:
             load_from_filename('tests/fixtures/extends/circle-1.yml')
-            raise Exception("Expected config.CircularReference to be raised")
-        except config.CircularReference as e:
-            self.assertEqual(
-                [(os.path.basename(filename), service_name) for (filename, service_name) in e.trail],
-                [
-                    ('circle-1.yml', 'web'),
-                    ('circle-2.yml', 'web'),
-                    ('circle-1.yml', 'web'),
-                ],
-            )
+
+        path = [
+            (os.path.basename(filename), service_name)
+            for (filename, service_name) in exc.value.trail
+        ]
+        expected = [
+            ('circle-1.yml', 'web'),
+            ('circle-2.yml', 'other'),
+            ('circle-1.yml', 'web'),
+        ]
+        self.assertEqual(path, expected)
 
     def test_extends_validation_empty_dictionary(self):
         with self.assertRaisesRegexp(ConfigurationError, 'service'):