diff --git a/compose/config/config.py b/compose/config/config.py index 1e077adcac..dbc6b6b22d 100644 --- a/compose/config/config.py +++ b/compose/config/config.py @@ -31,7 +31,6 @@ from .types import ServiceLink from .types import VolumeFromSpec from .types import VolumeSpec from .validation import match_named_volumes -from .validation import match_network_aliases from .validation import validate_against_fields_schema from .validation import validate_against_service_schema from .validation import validate_depends_on @@ -547,8 +546,6 @@ def validate_service(service_config, service_names, version): validate_network_mode(service_config, service_names) validate_depends_on(service_config, service_names) - match_network_aliases(service_config.config) - if not service_dict.get('image') and has_uppercase(service_name): raise ConfigurationError( "Service '{name}' contains uppercase characters which are not valid " diff --git a/compose/config/service_schema_v2.0.json b/compose/config/service_schema_v2.0.json index 1c8022d315..edccedc664 100644 --- a/compose/config/service_schema_v2.0.json +++ b/compose/config/service_schema_v2.0.json @@ -120,18 +120,28 @@ "network_mode": {"type": "string"}, "networks": { - "$ref": "#/definitions/list_of_strings" - }, - "network_aliases": { - "type": "object", - "patternProperties": { - "^[a-zA-Z0-9._-]+$": { - "$ref": "#/definitions/list_of_strings" + "oneOf": [ + {"$ref": "#/definitions/list_of_strings"}, + { + "type": "object", + "patternProperties": { + "^[a-zA-Z0-9._-]+$": { + "oneOf": [ + { + "type": "object", + "properties": { + "aliases": {"$ref": "#/definitions/list_of_strings"} + }, + "additionalProperties": false + }, + {"type": "null"} + ] + } + }, + "additionalProperties": false } - }, - "additionalProperties": false + ] }, - "pid": {"type": ["string", "null"]}, "ports": { diff --git a/compose/config/validation.py b/compose/config/validation.py index 59ce9f54e7..35727e2ccb 100644 --- a/compose/config/validation.py +++ b/compose/config/validation.py @@ -91,19 +91,6 @@ def match_named_volumes(service_dict, project_volumes): ) -def match_network_aliases(service_dict): - networks = service_dict.get('networks', []) - aliased_networks = service_dict.get('network_aliases', {}).keys() - for n in aliased_networks: - if n not in networks: - raise ConfigurationError( - 'Network "{0}" is referenced in network_aliases, but is not ' - 'declared in the networks list for service "{1}"'.format( - n, service_dict.get('name') - ) - ) - - def validate_top_level_service_objects(filename, service_dicts): """Perform some high level validation of the service name and value. diff --git a/compose/network.py b/compose/network.py index 99c04649b3..d17ed0805d 100644 --- a/compose/network.py +++ b/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, aliases=None): + ipam=None, external_name=None): self.client = client self.project = project self.name = name @@ -23,7 +23,6 @@ class Network(object): self.driver_opts = driver_opts self.ipam = create_ipam_config_from_dict(ipam) self.external_name = external_name - self.aliases = aliases or [] def ensure(self): if self.external_name: @@ -160,25 +159,32 @@ class ProjectNetworks(object): network.ensure() -def get_network_names_for_service(service_dict): +def get_network_aliases_for_service(service_dict): if 'network_mode' in service_dict: - return [] - return service_dict.get('networks', ['default']) + return {} + networks = service_dict.get('networks', ['default']) + if isinstance(networks, list): + return dict((net, []) for net in networks) + + return dict( + (net, (config or {}).get('aliases', [])) + for net, config in networks.items() + ) + + +def get_network_names_for_service(service_dict): + return get_network_aliases_for_service(service_dict).keys() def get_networks(service_dict, network_definitions): networks = {} - aliases = service_dict.get('network_aliases', {}) - for name in get_network_names_for_service(service_dict): - log.debug(name) + for name, aliases in get_network_aliases_for_service(service_dict).items(): network = network_definitions.get(name) if network: - log.debug(aliases) - networks[network.full_name] = aliases.get(name, []) + networks[network.full_name] = aliases else: raise ConfigurationError( 'Service "{}" uses an undefined network "{}"' .format(service_dict['name'], name)) - log.debug(networks) return networks diff --git a/docs/compose-file.md b/docs/compose-file.md index 2e9632c409..45e1ac0982 100644 --- a/docs/compose-file.md +++ b/docs/compose-file.md @@ -451,24 +451,6 @@ id. net: "none" net: "container:[service name or container name/id]" -### network_aliases - -> [Version 2 file format](#version-2) only. - -Alias names for this service on each joined network. All networks referenced -here must also appear under the `networks` key. - - networks: - - some-network - - other-network - network_aliases: - some-network: - - alias1 - - alias3 - other-network: - - alias2 - - alias4 - ### network_mode > [Version 2 file format](#version-2) only. In version 1, use [net](#net). @@ -493,6 +475,19 @@ Networks to join, referencing entries under the - some-network - other-network +#### aliases + +Alias names for this service on the specified network. + + networks: + some-network: + aliases: + - alias1 + - alias3 + other-network: + aliases: + - alias2 + ### pid pid: "host" diff --git a/tests/fixtures/networks/network-aliases.yml b/tests/fixtures/networks/network-aliases.yml index 987b0809a5..8cf7d5af94 100644 --- a/tests/fixtures/networks/network-aliases.yml +++ b/tests/fixtures/networks/network-aliases.yml @@ -5,13 +5,11 @@ services: image: busybox command: top networks: - - front - - back - - network_aliases: front: - - forward_facing - - ahead + aliases: + - forward_facing + - ahead + back: networks: front: {} diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 88d46a143b..1d6f1cbb09 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -556,27 +556,6 @@ class ConfigTest(unittest.TestCase): assert services[1]['name'] == 'db' assert services[2]['name'] == 'web' - def test_invalid_network_alias(self): - config_details = build_config_details({ - 'version': '2', - 'services': { - 'web': { - 'image': 'busybox', - 'networks': ['hello'], - 'network_aliases': { - 'world': ['planet', 'universe'] - } - } - }, - 'networks': { - 'hello': {}, - 'world': {} - } - }) - with pytest.raises(ConfigurationError) as exc: - config.load(config_details) - assert 'not declared in the networks list' in exc.exconly() - def test_config_build_configuration(self): service = config.load( build_config_details(