From 5545c55eccac1619bed2618621a2856bb79bc026 Mon Sep 17 00:00:00 2001 From: Dimitar Bonev Date: Fri, 22 Jan 2016 01:18:15 +0200 Subject: [PATCH] Network fields schema validation Signed-off-by: Dimitar Bonev --- compose/config/fields_schema_v2.json | 29 +++++++++++++++++++- docs/networking.md | 2 +- tests/unit/config/config_test.py | 41 ++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/compose/config/fields_schema_v2.json b/compose/config/fields_schema_v2.json index b0f304e86..c001df686 100644 --- a/compose/config/fields_schema_v2.json +++ b/compose/config/fields_schema_v2.json @@ -41,7 +41,34 @@ "definitions": { "network": { "id": "#/definitions/network", - "type": "object" + "type": "object", + "properties": { + "driver": {"type": "string"}, + "driver_opts": { + "type": "object", + "patternProperties": { + "^.+$": {"type": ["string", "number"]} + } + }, + "ipam": { + "type": "object", + "properties": { + "driver": {"type": "string"}, + "config": { + "type": "array" + } + }, + "additionalProperties": false + }, + "external": { + "type": ["boolean", "object"], + "properties": { + "name": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false }, "volume": { "id": "#/definitions/volume", diff --git a/docs/networking.md b/docs/networking.md index bcfd39e5f..1e662dd2c 100644 --- a/docs/networking.md +++ b/docs/networking.md @@ -106,7 +106,7 @@ Here's an example Compose file defining two custom networks. The `proxy` service back: # Use a custom driver which takes special options driver: my-custom-driver - options: + driver_opts: foo: "1" bar: "2" diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index eb8ed2c72..fe6098200 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -88,11 +88,26 @@ class ConfigTest(unittest.TestCase): 'driver': 'default', 'driver_opts': {'beep': 'boop'} } + }, + 'networks': { + 'default': { + 'driver': 'bridge', + 'driver_opts': {'beep': 'boop'} + }, + 'with_ipam': { + 'ipam': { + 'driver': 'default', + 'config': [ + {'subnet': '172.28.0.0/16'} + ] + } + } } }, 'working_dir', 'filename.yml') ) service_dicts = config_data.services volume_dict = config_data.volumes + networks_dict = config_data.networks self.assertEqual( service_sort(service_dicts), service_sort([ @@ -113,6 +128,20 @@ class ConfigTest(unittest.TestCase): 'driver_opts': {'beep': 'boop'} } }) + self.assertEqual(networks_dict, { + 'default': { + 'driver': 'bridge', + 'driver_opts': {'beep': 'boop'} + }, + 'with_ipam': { + 'ipam': { + 'driver': 'default', + 'config': [ + {'subnet': '172.28.0.0/16'} + ] + } + } + }) def test_named_volume_config_empty(self): config_details = build_config_details({ @@ -191,6 +220,18 @@ class ConfigTest(unittest.TestCase): ) ) + def test_load_throws_error_with_invalid_network_fields(self): + with self.assertRaises(ConfigurationError): + config.load( + build_config_details({ + 'version': 2, + 'services': {'web': 'busybox:latest'}, + 'networks': { + 'invalid': {'foo', 'bar'} + } + }, 'working_dir', 'filename.yml') + ) + def test_load_config_invalid_service_names(self): for invalid_name in ['?not?allowed', ' ', '', '!', '/', '\xe2']: with pytest.raises(ConfigurationError) as exc: