Explorar o código

Merge pull request #3473 from shin-/3461-merge-port-mappings

Eliminate duplicates when merging port mappings from config files
Aanand Prasad %!s(int64=9) %!d(string=hai) anos
pai
achega
86b5ed1a84

+ 7 - 7
compose/config/config.py

@@ -4,7 +4,6 @@ from __future__ import unicode_literals
 import functools
 import logging
 import ntpath
-import operator
 import os
 import string
 import sys
@@ -749,13 +748,10 @@ def merge_service_dicts(base, override, version):
         md.merge_field(field, merge_path_mappings)
 
     for field in [
-        'depends_on',
-        'expose',
-        'external_links',
-        'ports',
-        'volumes_from',
+        'ports', 'cap_add', 'cap_drop', 'expose', 'external_links',
+        'security_opt', 'volumes_from', 'depends_on',
     ]:
-        md.merge_field(field, operator.add, default=[])
+        md.merge_field(field, merge_unique_items_lists, default=[])
 
     for field in ['dns', 'dns_search', 'env_file', 'tmpfs']:
         md.merge_field(field, merge_list_or_string)
@@ -771,6 +767,10 @@ def merge_service_dicts(base, override, version):
     return dict(md)
 
 
+def merge_unique_items_lists(base, override):
+    return sorted(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'