Merge pull request #5566 from docker/mhank-5042-network-priorities

Add support for network priority
This commit is contained in:
Joffrey F 2018-01-12 14:40:17 -08:00 committed by GitHub
commit 7f22744658
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 92 additions and 11 deletions

View File

@ -191,7 +191,8 @@
"properties": { "properties": {
"aliases": {"$ref": "#/definitions/list_of_strings"}, "aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"}, "ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"} "ipv6_address": {"type": "string"},
"priority": {"type": "number"}
}, },
"additionalProperties": false "additionalProperties": false
}, },

View File

@ -217,7 +217,8 @@
"aliases": {"$ref": "#/definitions/list_of_strings"}, "aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"}, "ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"}, "ipv6_address": {"type": "string"},
"link_local_ips": {"$ref": "#/definitions/list_of_strings"} "link_local_ips": {"$ref": "#/definitions/list_of_strings"},
"priority": {"type": "number"}
}, },
"additionalProperties": false "additionalProperties": false
}, },

View File

@ -223,7 +223,8 @@
"aliases": {"$ref": "#/definitions/list_of_strings"}, "aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"}, "ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"}, "ipv6_address": {"type": "string"},
"link_local_ips": {"$ref": "#/definitions/list_of_strings"} "link_local_ips": {"$ref": "#/definitions/list_of_strings"},
"priority": {"type": "number"}
}, },
"additionalProperties": false "additionalProperties": false
}, },

View File

@ -226,7 +226,8 @@
"aliases": {"$ref": "#/definitions/list_of_strings"}, "aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"}, "ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"}, "ipv6_address": {"type": "string"},
"link_local_ips": {"$ref": "#/definitions/list_of_strings"} "link_local_ips": {"$ref": "#/definitions/list_of_strings"},
"priority": {"type": "number"}
}, },
"additionalProperties": false "additionalProperties": false
}, },

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import
from __future__ import unicode_literals from __future__ import unicode_literals
import logging import logging
from collections import OrderedDict
from docker.errors import NotFound from docker.errors import NotFound
from docker.types import IPAMConfig from docker.types import IPAMConfig
@ -286,4 +287,7 @@ def get_networks(service_dict, network_definitions):
'Service "{}" uses an undefined network "{}"' 'Service "{}" uses an undefined network "{}"'
.format(service_dict['name'], name)) .format(service_dict['name'], name))
return networks return OrderedDict(sorted(
networks.items(),
key=lambda t: t[1].get('priority') or 0, reverse=True
))

View File

@ -6,6 +6,7 @@ import os
import re import re
import sys import sys
from collections import namedtuple from collections import namedtuple
from collections import OrderedDict
from operator import attrgetter from operator import attrgetter
import enum import enum
@ -557,18 +558,25 @@ class Service(object):
raise OperationFailedError("Cannot start service %s: %s" % (self.name, ex.explanation)) raise OperationFailedError("Cannot start service %s: %s" % (self.name, ex.explanation))
return container return container
@property
def prioritized_networks(self):
return OrderedDict(
sorted(
self.networks.items(),
key=lambda t: t[1].get('priority') or 0, reverse=True
)
)
def connect_container_to_networks(self, container): def connect_container_to_networks(self, container):
connected_networks = container.get('NetworkSettings.Networks') connected_networks = container.get('NetworkSettings.Networks')
for network, netdefs in self.networks.items(): for network, netdefs in self.prioritized_networks.items():
if network in connected_networks: if network in connected_networks:
if short_id_alias_exists(container, network): if short_id_alias_exists(container, network):
continue continue
self.client.disconnect_container_from_network(container.id, network)
self.client.disconnect_container_from_network( log.debug('Connecting to {}'.format(network))
container.id,
network)
self.client.connect_container_to_network( self.client.connect_container_to_network(
container.id, network, container.id, network,
aliases=self._get_aliases(netdefs, container), aliases=self._get_aliases(netdefs, container),

View File

@ -1887,7 +1887,7 @@ class CLITestCase(DockerClientTestCase):
result = self.dispatch(['run', 'simple']) result = self.dispatch(['run', 'simple'])
if six.PY2: # Can't retrieve output on Py3. See issue #3670 if six.PY2: # Can't retrieve output on Py3. See issue #3670
assert value == result.stdout.strip() assert value in result.stdout.strip()
container = self.project.containers(one_off=OneOffFilter.only, stopped=True)[0] container = self.project.containers(one_off=OneOffFilter.only, stopped=True)[0]
environment = container.get('Config.Env') environment = container.get('Config.Env')

View File

@ -829,6 +829,71 @@ class ProjectTest(DockerClientTestCase):
assert ipam_config.get('IPv4Address') == '172.16.100.100' assert ipam_config.get('IPv4Address') == '172.16.100.100'
assert ipam_config.get('IPv6Address') == 'fe80::1001:102' assert ipam_config.get('IPv6Address') == 'fe80::1001:102'
@v2_3_only()
def test_up_with_network_priorities(self):
mac_address = '74:6f:75:68:6f:75'
def get_config_data(p1, p2, p3):
return build_config(
version=V2_3,
services=[{
'name': 'web',
'image': 'busybox:latest',
'networks': {
'n1': {
'priority': p1,
},
'n2': {
'priority': p2,
},
'n3': {
'priority': p3,
}
},
'command': 'top',
'mac_address': mac_address
}],
networks={
'n1': {},
'n2': {},
'n3': {}
}
)
config1 = get_config_data(1000, 1, 1)
config2 = get_config_data(2, 3, 1)
config3 = get_config_data(5, 40, 100)
project = Project.from_config(
client=self.client,
name='composetest',
config_data=config1
)
project.up(detached=True)
service_container = project.get_service('web').containers()[0]
net_config = service_container.inspect()['NetworkSettings']['Networks']['composetest_n1']
assert net_config['MacAddress'] == mac_address
project = Project.from_config(
client=self.client,
name='composetest',
config_data=config2
)
project.up(detached=True)
service_container = project.get_service('web').containers()[0]
net_config = service_container.inspect()['NetworkSettings']['Networks']['composetest_n2']
assert net_config['MacAddress'] == mac_address
project = Project.from_config(
client=self.client,
name='composetest',
config_data=config3
)
project.up(detached=True)
service_container = project.get_service('web').containers()[0]
net_config = service_container.inspect()['NetworkSettings']['Networks']['composetest_n3']
assert net_config['MacAddress'] == mac_address
@v2_1_only() @v2_1_only()
def test_up_with_enable_ipv6(self): def test_up_with_enable_ipv6(self):
self.require_api_version('1.23') self.require_api_version('1.23')