Implement network_mode in v2
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
parent
3f28472ebc
commit
2b7306967b
16 changed files with 405 additions and 87 deletions
|
|
@ -19,6 +19,7 @@ from .errors import CircularReference
|
|||
from .errors import ComposeFileNotFound
|
||||
from .errors import ConfigurationError
|
||||
from .interpolation import interpolate_environment_variables
|
||||
from .sort_services import get_container_name_from_net
|
||||
from .sort_services import get_service_name_from_net
|
||||
from .sort_services import sort_service_dicts
|
||||
from .types import parse_extra_hosts
|
||||
|
|
@ -30,6 +31,7 @@ from .validation import validate_against_fields_schema
|
|||
from .validation import validate_against_service_schema
|
||||
from .validation import validate_depends_on
|
||||
from .validation import validate_extends_file_path
|
||||
from .validation import validate_network_mode
|
||||
from .validation import validate_top_level_object
|
||||
from .validation import validate_top_level_service_objects
|
||||
from .validation import validate_ulimits
|
||||
|
|
@ -490,10 +492,15 @@ def validate_extended_service_dict(service_dict, filename, service):
|
|||
"%s services with 'volumes_from' cannot be extended" % error_prefix)
|
||||
|
||||
if 'net' in service_dict:
|
||||
if get_service_name_from_net(service_dict['net']) is not None:
|
||||
if get_container_name_from_net(service_dict['net']):
|
||||
raise ConfigurationError(
|
||||
"%s services with 'net: container' cannot be extended" % error_prefix)
|
||||
|
||||
if 'network_mode' in service_dict:
|
||||
if get_service_name_from_net(service_dict['network_mode']):
|
||||
raise ConfigurationError(
|
||||
"%s services with 'network_mode: service' cannot be extended" % error_prefix)
|
||||
|
||||
if 'depends_on' in service_dict:
|
||||
raise ConfigurationError(
|
||||
"%s services with 'depends_on' cannot be extended" % error_prefix)
|
||||
|
|
@ -505,6 +512,7 @@ def validate_service(service_config, service_names, version):
|
|||
validate_paths(service_dict)
|
||||
|
||||
validate_ulimits(service_config)
|
||||
validate_network_mode(service_config, service_names)
|
||||
validate_depends_on(service_config, service_names)
|
||||
|
||||
if not service_dict.get('image') and has_uppercase(service_name):
|
||||
|
|
@ -565,6 +573,14 @@ def finalize_service(service_config, service_names, version):
|
|||
service_dict['volumes'] = [
|
||||
VolumeSpec.parse(v) for v in service_dict['volumes']]
|
||||
|
||||
if 'net' in service_dict:
|
||||
network_mode = service_dict.pop('net')
|
||||
container_name = get_container_name_from_net(network_mode)
|
||||
if container_name and container_name in service_names:
|
||||
service_dict['network_mode'] = 'service:{}'.format(container_name)
|
||||
else:
|
||||
service_dict['network_mode'] = network_mode
|
||||
|
||||
if 'restart' in service_dict:
|
||||
service_dict['restart'] = parse_restart_spec(service_dict['restart'])
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
"mac_address": {"type": "string"},
|
||||
"mem_limit": {"type": ["number", "string"]},
|
||||
"memswap_limit": {"type": ["number", "string"]},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"type": "array",
|
||||
|
|
|
|||
|
|
@ -5,10 +5,18 @@ from compose.config.errors import DependencyError
|
|||
|
||||
|
||||
def get_service_name_from_net(net_config):
|
||||
return get_source_name_from_net(net_config, 'service')
|
||||
|
||||
|
||||
def get_container_name_from_net(net_config):
|
||||
return get_source_name_from_net(net_config, 'container')
|
||||
|
||||
|
||||
def get_source_name_from_net(net_config, source_type):
|
||||
if not net_config:
|
||||
return
|
||||
|
||||
if not net_config.startswith('container:'):
|
||||
if not net_config.startswith(source_type+':'):
|
||||
return
|
||||
|
||||
_, net_name = net_config.split(':', 1)
|
||||
|
|
@ -33,7 +41,7 @@ def sort_service_dicts(services):
|
|||
service for service in services
|
||||
if (name in get_service_names(service.get('links', [])) or
|
||||
name in get_service_names_from_volumes_from(service.get('volumes_from', [])) or
|
||||
name == get_service_name_from_net(service.get('net')) or
|
||||
name == get_service_name_from_net(service.get('network_mode')) or
|
||||
name in service.get('depends_on', []))
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from jsonschema import RefResolver
|
|||
from jsonschema import ValidationError
|
||||
|
||||
from .errors import ConfigurationError
|
||||
from .sort_services import get_service_name_from_net
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
@ -147,6 +148,24 @@ def validate_extends_file_path(service_name, extends_options, filename):
|
|||
)
|
||||
|
||||
|
||||
def validate_network_mode(service_config, service_names):
|
||||
network_mode = service_config.config.get('network_mode')
|
||||
if not network_mode:
|
||||
return
|
||||
|
||||
if 'networks' in service_config.config:
|
||||
raise ConfigurationError("'network_mode' and 'networks' cannot be combined")
|
||||
|
||||
dependency = get_service_name_from_net(network_mode)
|
||||
if not dependency:
|
||||
return
|
||||
|
||||
if dependency not in service_names:
|
||||
raise ConfigurationError(
|
||||
"Service '{s.name}' uses the network stack of service '{dep}' which "
|
||||
"is undefined.".format(s=service_config, dep=dependency))
|
||||
|
||||
|
||||
def validate_depends_on(service_config, service_names):
|
||||
for dependency in service_config.config.get('depends_on', []):
|
||||
if dependency not in service_names:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from docker.errors import NotFound
|
|||
|
||||
from . import parallel
|
||||
from .config import ConfigurationError
|
||||
from .config.sort_services import get_container_name_from_net
|
||||
from .config.sort_services import get_service_name_from_net
|
||||
from .const import DEFAULT_TIMEOUT
|
||||
from .const import IMAGE_EVENTS
|
||||
|
|
@ -86,12 +87,11 @@ class Project(object):
|
|||
for service_dict in config_data.services:
|
||||
if use_networking:
|
||||
networks = get_networks(service_dict, all_networks)
|
||||
net = Net(networks[0]) if networks else Net("none")
|
||||
else:
|
||||
networks = []
|
||||
net = project.get_net(service_dict)
|
||||
|
||||
links = project.get_links(service_dict)
|
||||
net = project.get_net(service_dict, networks)
|
||||
volumes_from = get_volumes_from(project, service_dict)
|
||||
|
||||
if config_data.version == 2:
|
||||
|
|
@ -197,27 +197,27 @@ class Project(object):
|
|||
del service_dict['links']
|
||||
return links
|
||||
|
||||
def get_net(self, service_dict):
|
||||
net = service_dict.pop('net', None)
|
||||
def get_net(self, service_dict, networks):
|
||||
net = service_dict.pop('network_mode', None)
|
||||
if not net:
|
||||
if self.use_networking:
|
||||
return Net(networks[0]) if networks else Net('none')
|
||||
return Net(None)
|
||||
|
||||
net_name = get_service_name_from_net(net)
|
||||
if not net_name:
|
||||
return Net(net)
|
||||
service_name = get_service_name_from_net(net)
|
||||
if service_name:
|
||||
return ServiceNet(self.get_service(service_name))
|
||||
|
||||
try:
|
||||
return ServiceNet(self.get_service(net_name))
|
||||
except NoSuchService:
|
||||
pass
|
||||
try:
|
||||
return ContainerNet(Container.from_id(self.client, net_name))
|
||||
except APIError:
|
||||
raise ConfigurationError(
|
||||
'Service "%s" is trying to use the network of "%s", '
|
||||
'which is not the name of a service or container.' % (
|
||||
service_dict['name'],
|
||||
net_name))
|
||||
container_name = get_container_name_from_net(net)
|
||||
if container_name:
|
||||
try:
|
||||
return ContainerNet(Container.from_id(self.client, container_name))
|
||||
except APIError:
|
||||
raise ConfigurationError(
|
||||
"Service '{name}' uses the network stack of container '{dep}' which "
|
||||
"does not exist.".format(name=service_dict['name'], dep=container_name))
|
||||
|
||||
return Net(net)
|
||||
|
||||
def start(self, service_names=None, **options):
|
||||
containers = []
|
||||
|
|
@ -465,9 +465,12 @@ class Project(object):
|
|||
|
||||
|
||||
def get_networks(service_dict, network_definitions):
|
||||
if 'network_mode' in service_dict:
|
||||
return []
|
||||
|
||||
networks = []
|
||||
for name in service_dict.pop('networks', ['default']):
|
||||
if name in ['bridge', 'host']:
|
||||
if name in ['bridge']:
|
||||
networks.append(name)
|
||||
else:
|
||||
matches = [n for n in network_definitions if n.name == name]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue