浏览代码

Fixes #2205 - extends must be copied from override file.

Signed-off-by: Daniel Nephin <[email protected]>
Daniel Nephin 10 年之前
父节点
当前提交
938d49cbdc
共有 2 个文件被更改,包括 52 次插入4 次删除
  1. 15 4
      compose/config/config.py
  2. 37 0
      tests/unit/config/config_test.py

+ 15 - 4
compose/config/config.py

@@ -193,7 +193,9 @@ def load(config_details):
     def merge_services(base, override):
         all_service_names = set(base) | set(override)
         return {
-            name: merge_service_dicts(base.get(name, {}), override.get(name, {}))
+            name: merge_service_dicts_from_files(
+                base.get(name, {}),
+                override.get(name, {}))
             for name in all_service_names
         }
 
@@ -270,9 +272,7 @@ class ServiceLoader(object):
             extends,
             self.filename
         )
-        self.extended_config_path = self.get_extended_config_path(
-            extends
-        )
+        self.extended_config_path = self.get_extended_config_path(extends)
         self.extended_service_name = extends['service']
 
         config = load_yaml(self.extended_config_path)
@@ -355,6 +355,17 @@ def process_container_options(service_dict, working_dir=None):
     return service_dict
 
 
+def merge_service_dicts_from_files(base, override):
+    """When merging services from multiple files we need to merge the `extends`
+    field. This is not handled by `merge_service_dicts()` which is used to
+    perform the `extends`.
+    """
+    new_service = merge_service_dicts(base, override)
+    if 'extends' in override:
+        new_service['extends'] = override['extends']
+    return new_service
+
+
 def merge_service_dicts(base, override):
     d = base.copy()
 

+ 37 - 0
tests/unit/config/config_test.py

@@ -156,6 +156,43 @@ class ConfigTest(unittest.TestCase):
             config.load(details)
         assert 'Top level object needs to be a dictionary' in exc.exconly()
 
+    def test_load_with_multiple_files_and_extends_in_override_file(self):
+        base_file = config.ConfigFile(
+            'base.yaml',
+            {
+                'web': {'image': 'example/web'},
+            })
+        override_file = config.ConfigFile(
+            'override.yaml',
+            {
+                'web': {
+                    'extends': {
+                        'file': 'common.yml',
+                        'service': 'base',
+                    },
+                    'volumes': ['/home/user/project:/code'],
+                },
+            })
+        details = config.ConfigDetails('.', [base_file, override_file])
+
+        tmpdir = py.test.ensuretemp('config_test')
+        tmpdir.join('common.yml').write("""
+            base:
+              labels: ['label=one']
+        """)
+        with tmpdir.as_cwd():
+            service_dicts = config.load(details)
+
+        expected = [
+            {
+                'name': 'web',
+                'image': 'example/web',
+                'volumes': ['/home/user/project:/code'],
+                'labels': {'label': 'one'},
+            },
+        ]
+        self.assertEqual(service_sort(service_dicts), service_sort(expected))
+
     def test_config_valid_service_names(self):
         for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']:
             config.load(