소스 검색

Add support for creating internal networks

Signed-off-by: Jonathan Giannuzzi <[email protected]>
Jonathan Giannuzzi 9 년 전
부모
커밋
83f35e132b

+ 2 - 1
compose/config/config_schema_v2.0.json

@@ -246,7 +246,8 @@
             "name": {"type": "string"}
           },
           "additionalProperties": false
-        }
+        },
+        "internal": {"type": "boolean"}
       },
       "additionalProperties": false
     },

+ 4 - 1
compose/network.py

@@ -15,7 +15,7 @@ log = logging.getLogger(__name__)
 
 class Network(object):
     def __init__(self, client, project, name, driver=None, driver_opts=None,
-                 ipam=None, external_name=None):
+                 ipam=None, external_name=None, internal=False):
         self.client = client
         self.project = project
         self.name = name
@@ -23,6 +23,7 @@ class Network(object):
         self.driver_opts = driver_opts
         self.ipam = create_ipam_config_from_dict(ipam)
         self.external_name = external_name
+        self.internal = internal
 
     def ensure(self):
         if self.external_name:
@@ -68,6 +69,7 @@ class Network(object):
                 driver=self.driver,
                 options=self.driver_opts,
                 ipam=self.ipam,
+                internal=self.internal,
             )
 
     def remove(self):
@@ -115,6 +117,7 @@ def build_networks(name, config_data, client):
             driver_opts=data.get('driver_opts'),
             ipam=data.get('ipam'),
             external_name=data.get('external_name'),
+            internal=data.get('internal'),
         )
         for network_name, data in network_config.items()
     }

+ 5 - 1
docs/compose-file.md

@@ -859,6 +859,10 @@ A full example:
             host2: 172.28.1.6
             host3: 172.28.1.7
 
+### internal
+
+By default, Docker also connects a bridge network to it to provide external connectivity. If you want to create an externally isolated overlay network, you can set this option to `true`.
+
 ### external
 
 If set to `true`, specifies that this network has been created outside of
@@ -866,7 +870,7 @@ Compose. `docker-compose up` will not attempt to create it, and will raise
 an error if it doesn't exist.
 
 `external` cannot be used in conjunction with other network configuration keys
-(`driver`, `driver_opts`, `ipam`).
+(`driver`, `driver_opts`, `ipam`, `internal`).
 
 In the example below, `proxy` is the gateway to the outside world. Instead of
 attemping to create a network called `[projectname]_outside`, Compose will

+ 18 - 0
tests/acceptance/cli_test.py

@@ -576,6 +576,24 @@ class CLITestCase(DockerClientTestCase):
         assert 'forward_facing' in front_aliases
         assert 'ahead' in front_aliases
 
+    @v2_only()
+    def test_up_with_network_internal(self):
+        self.require_api_version('1.23')
+        filename = 'network-internal.yml'
+        self.base_dir = 'tests/fixtures/networks'
+        self.dispatch(['-f', filename, 'up', '-d'], None)
+        internal_net = '{}_internal'.format(self.project.name)
+
+        networks = [
+            n for n in self.client.networks()
+            if n['Name'].startswith('{}_'.format(self.project.name))
+        ]
+
+        # One network was created: internal
+        assert sorted(n['Name'] for n in networks) == [internal_net]
+
+        assert networks[0]['Internal'] is True
+
     @v2_only()
     def test_up_with_network_static_addresses(self):
         filename = 'network-static-addresses.yml'

+ 13 - 0
tests/fixtures/networks/network-internal.yml

@@ -0,0 +1,13 @@
+version: "2"
+
+services:
+  web:
+    image: busybox
+    command: top
+    networks:
+      - internal
+
+networks:
+  internal:
+    driver: bridge
+    internal: True

+ 27 - 0
tests/integration/project_test.py

@@ -756,6 +756,33 @@ class ProjectTest(DockerClientTestCase):
         with self.assertRaises(ProjectError):
             project.up()
 
+    @v2_only()
+    def test_project_up_with_network_internal(self):
+        self.require_api_version('1.23')
+        config_data = config.Config(
+            version=V2_0,
+            services=[{
+                'name': 'web',
+                'image': 'busybox:latest',
+                'networks': {'internal': None},
+            }],
+            volumes={},
+            networks={
+                'internal': {'driver': 'bridge', 'internal': True},
+            },
+        )
+
+        project = Project.from_config(
+            client=self.client,
+            name='composetest',
+            config_data=config_data,
+        )
+        project.up()
+
+        network = self.client.networks(names=['composetest_internal'])[0]
+
+        assert network['Internal'] is True
+
     @v2_only()
     def test_project_up_volumes(self):
         vol_name = '{0:x}'.format(random.getrandbits(32))

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

@@ -101,6 +101,10 @@ class ConfigTest(unittest.TestCase):
                                 {'subnet': '172.28.0.0/16'}
                             ]
                         }
+                    },
+                    'internal': {
+                        'driver': 'bridge',
+                        'internal': True
                     }
                 }
             }, 'working_dir', 'filename.yml')
@@ -140,6 +144,10 @@ class ConfigTest(unittest.TestCase):
                         {'subnet': '172.28.0.0/16'}
                     ]
                 }
+            },
+            'internal': {
+                'driver': 'bridge',
+                'internal': True
             }
         })