mirror of https://github.com/docker/docker-py.git
Add support for publish mode for endpointspec ports
Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
0750337f6a
commit
5347c168d0
|
@ -3,7 +3,7 @@ from .. import auth, errors, utils
|
|||
from ..types import ServiceMode
|
||||
|
||||
|
||||
def _check_api_features(version, task_template, update_config):
|
||||
def _check_api_features(version, task_template, update_config, endpoint_spec):
|
||||
|
||||
def raise_version_error(param, min_version):
|
||||
raise errors.InvalidVersion(
|
||||
|
@ -23,6 +23,11 @@ def _check_api_features(version, task_template, update_config):
|
|||
if 'Order' in update_config:
|
||||
raise_version_error('UpdateConfig.order', '1.29')
|
||||
|
||||
if endpoint_spec is not None:
|
||||
if utils.version_lt(version, '1.32') and 'Ports' in endpoint_spec:
|
||||
if any(p.get('PublishMode') for p in endpoint_spec['Ports']):
|
||||
raise_version_error('EndpointSpec.Ports[].mode', '1.32')
|
||||
|
||||
if task_template is not None:
|
||||
if 'ForceUpdate' in task_template and utils.version_lt(
|
||||
version, '1.25'):
|
||||
|
@ -125,7 +130,9 @@ class ServiceApiMixin(object):
|
|||
)
|
||||
endpoint_spec = endpoint_config
|
||||
|
||||
_check_api_features(self._version, task_template, update_config)
|
||||
_check_api_features(
|
||||
self._version, task_template, update_config, endpoint_spec
|
||||
)
|
||||
|
||||
url = self._url('/services/create')
|
||||
headers = {}
|
||||
|
@ -370,7 +377,9 @@ class ServiceApiMixin(object):
|
|||
)
|
||||
endpoint_spec = endpoint_config
|
||||
|
||||
_check_api_features(self._version, task_template, update_config)
|
||||
_check_api_features(
|
||||
self._version, task_template, update_config, endpoint_spec
|
||||
)
|
||||
|
||||
if fetch_current_spec:
|
||||
inspect_defaults = True
|
||||
|
|
|
@ -450,8 +450,9 @@ class EndpointSpec(dict):
|
|||
``'vip'`` if not provided.
|
||||
ports (dict): Exposed ports that this service is accessible on from the
|
||||
outside, in the form of ``{ published_port: target_port }`` or
|
||||
``{ published_port: (target_port, protocol) }``. Ports can only be
|
||||
provided if the ``vip`` resolution mode is used.
|
||||
``{ published_port: <port_config_tuple> }``. Port config tuple format
|
||||
is ``(target_port [, protocol [, publish_mode]])``.
|
||||
Ports can only be provided if the ``vip`` resolution mode is used.
|
||||
"""
|
||||
def __init__(self, mode=None, ports=None):
|
||||
if ports:
|
||||
|
@ -477,8 +478,15 @@ def convert_service_ports(ports):
|
|||
|
||||
if isinstance(v, tuple):
|
||||
port_spec['TargetPort'] = v[0]
|
||||
if len(v) == 2:
|
||||
if len(v) >= 2 and v[1] is not None:
|
||||
port_spec['Protocol'] = v[1]
|
||||
if len(v) == 3:
|
||||
port_spec['PublishMode'] = v[2]
|
||||
if len(v) > 3:
|
||||
raise ValueError(
|
||||
'Service port configuration can have at most 3 elements: '
|
||||
'(target_port, protocol, mode)'
|
||||
)
|
||||
else:
|
||||
port_spec['TargetPort'] = v
|
||||
|
||||
|
|
|
@ -353,7 +353,6 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
task_tmpl, name=name, endpoint_spec=endpoint_spec
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
print(svc_info)
|
||||
ports = svc_info['Spec']['EndpointSpec']['Ports']
|
||||
for port in ports:
|
||||
if port['PublishedPort'] == 12562:
|
||||
|
@ -370,6 +369,26 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
|
||||
assert len(ports) == 3
|
||||
|
||||
@requires_api_version('1.32')
|
||||
def test_create_service_with_endpoint_spec_host_publish_mode(self):
|
||||
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
name = self.get_service_name()
|
||||
endpoint_spec = docker.types.EndpointSpec(ports={
|
||||
12357: (1990, None, 'host'),
|
||||
})
|
||||
svc_id = self.client.create_service(
|
||||
task_tmpl, name=name, endpoint_spec=endpoint_spec
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
ports = svc_info['Spec']['EndpointSpec']['Ports']
|
||||
assert len(ports) == 1
|
||||
port = ports[0]
|
||||
assert port['PublishedPort'] == 12357
|
||||
assert port['TargetPort'] == 1990
|
||||
assert port['Protocol'] == 'tcp'
|
||||
assert port['PublishMode'] == 'host'
|
||||
|
||||
def test_create_service_with_env(self):
|
||||
container_spec = docker.types.ContainerSpec(
|
||||
BUSYBOX, ['true'], env={'DOCKER_PY_TEST': 1}
|
||||
|
|
|
@ -11,6 +11,7 @@ from docker.types import (
|
|||
ContainerConfig, ContainerSpec, EndpointConfig, HostConfig, IPAMConfig,
|
||||
IPAMPool, LogConfig, Mount, ServiceMode, Ulimit,
|
||||
)
|
||||
from docker.types.services import convert_service_ports
|
||||
|
||||
try:
|
||||
from unittest import mock
|
||||
|
@ -423,3 +424,77 @@ class MountTest(unittest.TestCase):
|
|||
assert mount['Source'] == "C:/foo/bar"
|
||||
assert mount['Target'] == "/baz"
|
||||
assert mount['Type'] == 'bind'
|
||||
|
||||
|
||||
class ServicePortsTest(unittest.TestCase):
|
||||
def test_convert_service_ports_simple(self):
|
||||
ports = {8080: 80}
|
||||
assert convert_service_ports(ports) == [{
|
||||
'Protocol': 'tcp',
|
||||
'PublishedPort': 8080,
|
||||
'TargetPort': 80,
|
||||
}]
|
||||
|
||||
def test_convert_service_ports_with_protocol(self):
|
||||
ports = {8080: (80, 'udp')}
|
||||
|
||||
assert convert_service_ports(ports) == [{
|
||||
'Protocol': 'udp',
|
||||
'PublishedPort': 8080,
|
||||
'TargetPort': 80,
|
||||
}]
|
||||
|
||||
def test_convert_service_ports_with_protocol_and_mode(self):
|
||||
ports = {8080: (80, 'udp', 'ingress')}
|
||||
|
||||
assert convert_service_ports(ports) == [{
|
||||
'Protocol': 'udp',
|
||||
'PublishedPort': 8080,
|
||||
'TargetPort': 80,
|
||||
'PublishMode': 'ingress',
|
||||
}]
|
||||
|
||||
def test_convert_service_ports_invalid(self):
|
||||
ports = {8080: ('way', 'too', 'many', 'items', 'here')}
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
convert_service_ports(ports)
|
||||
|
||||
def test_convert_service_ports_no_protocol_and_mode(self):
|
||||
ports = {8080: (80, None, 'host')}
|
||||
|
||||
assert convert_service_ports(ports) == [{
|
||||
'Protocol': 'tcp',
|
||||
'PublishedPort': 8080,
|
||||
'TargetPort': 80,
|
||||
'PublishMode': 'host',
|
||||
}]
|
||||
|
||||
def test_convert_service_ports_multiple(self):
|
||||
ports = {
|
||||
8080: (80, None, 'host'),
|
||||
9999: 99,
|
||||
2375: (2375,)
|
||||
}
|
||||
|
||||
converted_ports = convert_service_ports(ports)
|
||||
assert {
|
||||
'Protocol': 'tcp',
|
||||
'PublishedPort': 8080,
|
||||
'TargetPort': 80,
|
||||
'PublishMode': 'host',
|
||||
} in converted_ports
|
||||
|
||||
assert {
|
||||
'Protocol': 'tcp',
|
||||
'PublishedPort': 9999,
|
||||
'TargetPort': 99,
|
||||
} in converted_ports
|
||||
|
||||
assert {
|
||||
'Protocol': 'tcp',
|
||||
'PublishedPort': 2375,
|
||||
'TargetPort': 2375,
|
||||
} in converted_ports
|
||||
|
||||
assert len(converted_ports) == 3
|
||||
|
|
Loading…
Reference in New Issue