diff --git a/compose/config/config_schema_v2.0.json b/compose/config/config_schema_v2.0.json index 54e9b3314..f3688685b 100644 --- a/compose/config/config_schema_v2.0.json +++ b/compose/config/config_schema_v2.0.json @@ -253,6 +253,13 @@ "driver": {"type": "string"}, "config": { "type": "array" + }, + "options": { + "type": "object", + "patternProperties": { + "^.+$": {"type": "string"} + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/compose/config/config_schema_v2.1.json b/compose/config/config_schema_v2.1.json index 0f87be24e..aa59d181e 100644 --- a/compose/config/config_schema_v2.1.json +++ b/compose/config/config_schema_v2.1.json @@ -298,6 +298,13 @@ "driver": {"type": "string"}, "config": { "type": "array" + }, + "options": { + "type": "object", + "patternProperties": { + "^.+$": {"type": "string"} + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/compose/network.py b/compose/network.py index 053fdacd8..4aeff2d1e 100644 --- a/compose/network.py +++ b/compose/network.py @@ -123,6 +123,7 @@ def create_ipam_config_from_dict(ipam_dict): ) for config in ipam_dict.get('config', []) ], + options=ipam_dict.get('options') ) @@ -157,6 +158,12 @@ def check_remote_ipam_config(remote, local): if sorted(lc.get('AuxiliaryAddresses')) != sorted(rc.get('AuxiliaryAddresses')): raise NetworkConfigChangedError(local.full_name, 'IPAM config aux_addresses') + remote_opts = remote_ipam.get('Options', {}) + local_opts = local.ipam.get('options', {}) + for k in set.union(set(remote_opts.keys()), set(local_opts.keys())): + if remote_opts.get(k) != local_opts.get(k): + raise NetworkConfigChangedError(local.full_name, 'IPAM option "{}"'.format(k)) + def check_remote_network_config(remote, local): if local.driver and remote.get('Driver') != local.driver: diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py index 455189851..2eae88ec5 100644 --- a/tests/integration/project_test.py +++ b/tests/integration/project_test.py @@ -681,6 +681,41 @@ class ProjectTest(DockerClientTestCase): }], } + @v2_only() + def test_up_with_ipam_options(self): + config_data = build_config( + version=V2_0, + services=[{ + 'name': 'web', + 'image': 'busybox:latest', + 'networks': {'front': None}, + }], + networks={ + 'front': { + 'driver': 'bridge', + 'ipam': { + 'driver': 'default', + 'options': { + "com.docker.compose.network.test": "9-29-045" + } + }, + }, + }, + ) + + project = Project.from_config( + client=self.client, + name='composetest', + config_data=config_data, + ) + project.up() + + network = self.client.networks(names=['composetest_front'])[0] + + assert network['IPAM']['Options'] == { + "com.docker.compose.network.test": "9-29-045" + } + @v2_only() def test_up_with_network_static_addresses(self): config_data = build_config(