diff --git a/compose/config/config_schema_v2.0.json b/compose/config/config_schema_v2.0.json index eddf787ea..793cef1d6 100644 --- a/compose/config/config_schema_v2.0.json +++ b/compose/config/config_schema_v2.0.json @@ -281,7 +281,8 @@ "properties": { "driver": {"type": "string"}, "config": { - "type": "array" + "type": "array", + "items": {"$ref": "#/definitions/ipam_config"} }, "options": { "type": "object", @@ -305,6 +306,24 @@ "additionalProperties": false }, + "ipam_config": { + "id": "#/definitions/ipam_config", + "type": "object", + "properties": { + "subnet": {"type": "string"}, + "iprange": {"type": "string"}, + "gateway": {"type": "string"}, + "aux_addresses": { + "type": "object", + "patternProperties": { + "^.+$": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "volume": { "id": "#/definitions/volume", "type": ["object", "null"], diff --git a/compose/config/config_schema_v2.1.json b/compose/config/config_schema_v2.1.json index 5ad5a20ea..5ea763544 100644 --- a/compose/config/config_schema_v2.1.json +++ b/compose/config/config_schema_v2.1.json @@ -332,7 +332,8 @@ "properties": { "driver": {"type": "string"}, "config": { - "type": "array" + "type": "array", + "items": {"$ref": "#/definitions/ipam_config"} }, "options": { "type": "object", @@ -359,6 +360,24 @@ "additionalProperties": false }, + "ipam_config": { + "id": "#/definitions/ipam_config", + "type": "object", + "properties": { + "subnet": {"type": "string"}, + "iprange": {"type": "string"}, + "gateway": {"type": "string"}, + "aux_addresses": { + "type": "object", + "patternProperties": { + "^.+$": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "volume": { "id": "#/definitions/volume", "type": ["object", "null"], diff --git a/compose/config/config_schema_v2.2.json b/compose/config/config_schema_v2.2.json index 26044b651..a19d4c945 100644 --- a/compose/config/config_schema_v2.2.json +++ b/compose/config/config_schema_v2.2.json @@ -341,7 +341,8 @@ "properties": { "driver": {"type": "string"}, "config": { - "type": "array" + "type": "array", + "items": {"$ref": "#/definitions/ipam_config"} }, "options": { "type": "object", @@ -368,6 +369,24 @@ "additionalProperties": false }, + "ipam_config": { + "id": "#/definitions/ipam_config", + "type": "object", + "properties": { + "subnet": {"type": "string"}, + "iprange": {"type": "string"}, + "gateway": {"type": "string"}, + "aux_addresses": { + "type": "object", + "patternProperties": { + "^.+$": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "volume": { "id": "#/definitions/volume", "type": ["object", "null"], diff --git a/compose/config/config_schema_v2.3.json b/compose/config/config_schema_v2.3.json index ac0778f2a..78b716a7a 100644 --- a/compose/config/config_schema_v2.3.json +++ b/compose/config/config_schema_v2.3.json @@ -385,7 +385,8 @@ "properties": { "driver": {"type": "string"}, "config": { - "type": "array" + "type": "array", + "items": {"$ref": "#/definitions/ipam_config"} }, "options": { "type": "object", @@ -412,6 +413,24 @@ "additionalProperties": false }, + "ipam_config": { + "id": "#/definitions/ipam_config", + "type": "object", + "properties": { + "subnet": {"type": "string"}, + "iprange": {"type": "string"}, + "gateway": {"type": "string"}, + "aux_addresses": { + "type": "object", + "patternProperties": { + "^.+$": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "volume": { "id": "#/definitions/volume", "type": ["object", "null"], diff --git a/compose/config/config_schema_v2.4.json b/compose/config/config_schema_v2.4.json index 731fa2f9b..a5796d5b1 100644 --- a/compose/config/config_schema_v2.4.json +++ b/compose/config/config_schema_v2.4.json @@ -384,7 +384,8 @@ "properties": { "driver": {"type": "string"}, "config": { - "type": "array" + "type": "array", + "items": {"$ref": "#/definitions/ipam_config"} }, "options": { "type": "object", @@ -411,6 +412,24 @@ "additionalProperties": false }, + "ipam_config": { + "id": "#/definitions/ipam_config", + "type": "object", + "properties": { + "subnet": {"type": "string"}, + "iprange": {"type": "string"}, + "gateway": {"type": "string"}, + "aux_addresses": { + "type": "object", + "patternProperties": { + "^.+$": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "volume": { "id": "#/definitions/volume", "type": ["object", "null"], diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 8a75648ac..4562a99ca 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -1322,6 +1322,28 @@ class ConfigTest(unittest.TestCase): assert mount.type == 'bind' assert mount.source == expected_source + def test_config_invalid_ipam_config(self): + with pytest.raises(ConfigurationError) as excinfo: + config.load( + build_config_details( + { + 'version': str(V2_1), + 'networks': { + 'foo': { + 'driver': 'default', + 'ipam': { + 'driver': 'default', + 'config': ['172.18.0.0/16'], + } + } + } + }, + filename='filename.yml', + ) + ) + assert ('networks.foo.ipam.config contains an invalid type,' + ' it should be an object') in excinfo.exconly() + def test_config_valid_service_names(self): for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']: services = config.load(