Browse Source

Eliminate duplicates when merging port mappings from config files

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 9 years ago
parent
commit
842e372258
3 changed files with 49 additions and 1 deletions
  1. 5 1
      compose/config/config.py
  2. 36 0
      tests/integration/project_test.py
  3. 8 0
      tests/unit/config/config_test.py

+ 5 - 1
compose/config/config.py

@@ -744,6 +744,7 @@ def merge_service_dicts(base, override, version):
     md.merge_mapping('ulimits', parse_ulimits)
     md.merge_mapping('networks', parse_networks)
     md.merge_sequence('links', ServiceLink.parse)
+    md.merge_field('ports', merge_port_mappings, default=[])
 
     for field in ['volumes', 'devices']:
         md.merge_field(field, merge_path_mappings)
@@ -752,7 +753,6 @@ def merge_service_dicts(base, override, version):
         'depends_on',
         'expose',
         'external_links',
-        'ports',
         'volumes_from',
     ]:
         md.merge_field(field, operator.add, default=[])
@@ -771,6 +771,10 @@ def merge_service_dicts(base, override, version):
     return dict(md)
 
 
+def merge_port_mappings(base, override):
+    return list(set().union(base, override))
+
+
 def merge_build(output, base, override):
     def to_dict(service):
         build_config = service.get('build', {})

+ 36 - 0
tests/integration/project_test.py

@@ -834,6 +834,42 @@ class ProjectTest(DockerClientTestCase):
         self.assertTrue(log_config)
         self.assertEqual(log_config.get('Type'), 'none')
 
+    @v2_only()
+    def test_project_up_port_mappings_with_multiple_files(self):
+        base_file = config.ConfigFile(
+            'base.yml',
+            {
+                'version': V2_0,
+                'services': {
+                    'simple': {
+                        'image': 'busybox:latest',
+                        'command': 'top',
+                        'ports': ['1234:1234']
+                    },
+                },
+
+            })
+        override_file = config.ConfigFile(
+            'override.yml',
+            {
+                'version': V2_0,
+                'services': {
+                    'simple': {
+                        'ports': ['1234:1234']
+                    }
+                }
+
+            })
+        details = config.ConfigDetails('.', [base_file, override_file])
+
+        config_data = config.load(details)
+        project = Project.from_config(
+            name='composetest', config_data=config_data, client=self.client
+        )
+        project.up()
+        containers = project.containers()
+        self.assertEqual(len(containers), 1)
+
     @v2_only()
     def test_initialize_volumes(self):
         vol_name = '{0:x}'.format(random.getrandbits(32))

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

@@ -1912,6 +1912,14 @@ class MergePortsTest(unittest.TestCase, MergeListsTest):
     base_config = ['10:8000', '9000']
     override_config = ['20:8000']
 
+    def test_duplicate_port_mappings(self):
+        service_dict = config.merge_service_dicts(
+            {self.config_name: self.base_config},
+            {self.config_name: self.base_config},
+            DEFAULT_VERSION
+        )
+        assert set(service_dict[self.config_name]) == set(self.base_config)
+
 
 class MergeNetworksTest(unittest.TestCase, MergeListsTest):
     config_name = 'networks'