mirror of https://github.com/docker/docker-py.git
Service model update changes
Signed-off-by: Viktor Adam <rycus86@gmail.com>
This commit is contained in:
parent
6e5eb2eba7
commit
b2d08e64bc
|
@ -363,8 +363,15 @@ class ServiceApiMixin(object):
|
|||
data = {}
|
||||
headers = {}
|
||||
|
||||
data['Name'] = name if name is not None else current.get('Name')
|
||||
data['Labels'] = labels if labels is not None else current.get('Labels')
|
||||
if name is not None:
|
||||
data['Name'] = name
|
||||
else:
|
||||
data['Name'] = current.get('Name')
|
||||
|
||||
if labels is not None:
|
||||
data['Labels'] = labels
|
||||
else:
|
||||
data['Labels'] = current.get('Labels')
|
||||
|
||||
if mode is not None:
|
||||
if not isinstance(mode, dict):
|
||||
|
@ -373,23 +380,17 @@ class ServiceApiMixin(object):
|
|||
else:
|
||||
data['Mode'] = current.get('Mode')
|
||||
|
||||
merged_task_template = current.get('TaskTemplate', {})
|
||||
if task_template is not None:
|
||||
for task_template_key, task_template_value in task_template.items():
|
||||
if task_template_key == 'ContainerSpec':
|
||||
if 'ContainerSpec' not in merged_task_template:
|
||||
merged_task_template['ContainerSpec'] = {}
|
||||
for container_spec_key, container_spec_value in task_template['ContainerSpec'].items():
|
||||
merged_task_template['ContainerSpec'][container_spec_key] = container_spec_value
|
||||
else:
|
||||
merged_task_template[task_template_key] = task_template_value
|
||||
image = merged_task_template.get('ContainerSpec', {}).get('Image', None)
|
||||
if image is not None:
|
||||
registry, repo_name = auth.resolve_repository_name(image)
|
||||
auth_header = auth.get_config_header(self, registry)
|
||||
if auth_header:
|
||||
headers['X-Registry-Auth'] = auth_header
|
||||
data['TaskTemplate'] = merged_task_template
|
||||
data['TaskTemplate'] = self._merge_task_template(
|
||||
current.get('TaskTemplate', {}), task_template
|
||||
)
|
||||
|
||||
container_spec = data['TaskTemplate'].get('ContainerSpec', {})
|
||||
image = container_spec.get('Image', None)
|
||||
if image is not None:
|
||||
registry, repo_name = auth.resolve_repository_name(image)
|
||||
auth_header = auth.get_config_header(self, registry)
|
||||
if auth_header:
|
||||
headers['X-Registry-Auth'] = auth_header
|
||||
|
||||
if update_config is not None:
|
||||
data['UpdateConfig'] = update_config
|
||||
|
@ -397,11 +398,15 @@ class ServiceApiMixin(object):
|
|||
data['UpdateConfig'] = current.get('UpdateConfig')
|
||||
|
||||
if networks is not None:
|
||||
data['TaskTemplate']['Networks'] = utils.convert_service_networks(networks)
|
||||
else:
|
||||
existing_networks = current.get('TaskTemplate', {}).get('Networks') or current.get('Networks')
|
||||
if existing_networks is not None:
|
||||
data['TaskTemplate']['Networks'] = existing_networks
|
||||
converted_networks = utils.convert_service_networks(networks)
|
||||
data['TaskTemplate']['Networks'] = converted_networks
|
||||
elif data['TaskTemplate'].get('Networks') is None:
|
||||
current_task_template = current.get('TaskTemplate', {})
|
||||
current_networks = current_task_template.get('Networks')
|
||||
if current_networks is None:
|
||||
current_networks = current.get('Networks')
|
||||
if current_networks is not None:
|
||||
data['TaskTemplate']['Networks'] = current_networks
|
||||
|
||||
if endpoint_spec is not None:
|
||||
data['EndpointSpec'] = endpoint_spec
|
||||
|
@ -413,3 +418,17 @@ class ServiceApiMixin(object):
|
|||
)
|
||||
self._raise_for_status(resp)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _merge_task_template(current, override):
|
||||
merged = current.copy()
|
||||
if override is not None:
|
||||
for ts_key, ts_value in override.items():
|
||||
if ts_key == 'ContainerSpec':
|
||||
if 'ContainerSpec' not in merged:
|
||||
merged['ContainerSpec'] = {}
|
||||
for cs_key, cs_value in override['ContainerSpec'].items():
|
||||
merged['ContainerSpec'][cs_key] = cs_value
|
||||
else:
|
||||
merged[ts_key] = ts_value
|
||||
return merged
|
||||
|
|
|
@ -251,6 +251,7 @@ CONTAINER_SPEC_KWARGS = [
|
|||
|
||||
# kwargs to copy straight over to TaskTemplate
|
||||
TASK_TEMPLATE_KWARGS = [
|
||||
'networks',
|
||||
'resources',
|
||||
'restart_policy',
|
||||
]
|
||||
|
@ -261,7 +262,6 @@ CREATE_SERVICE_KWARGS = [
|
|||
'labels',
|
||||
'mode',
|
||||
'update_config',
|
||||
'networks',
|
||||
'endpoint_spec',
|
||||
]
|
||||
|
||||
|
@ -295,6 +295,15 @@ def _get_create_service_kwargs(func_name, kwargs):
|
|||
'Options': kwargs.pop('log_driver_options', {})
|
||||
}
|
||||
|
||||
if func_name == 'update':
|
||||
if 'force_update' in kwargs:
|
||||
task_template_kwargs['force_update'] = kwargs.pop('force_update')
|
||||
|
||||
# use the current spec by default if updating the service
|
||||
# through the model
|
||||
use_current_spec = kwargs.pop('use_current_spec', True)
|
||||
create_kwargs['use_current_spec'] = use_current_spec
|
||||
|
||||
# All kwargs should have been consumed by this point, so raise
|
||||
# error if any are left
|
||||
if kwargs:
|
||||
|
|
|
@ -4,7 +4,7 @@ from .. import errors
|
|||
from ..constants import IS_WINDOWS_PLATFORM
|
||||
from ..utils import (
|
||||
check_resource, format_environment, format_extra_hosts, parse_bytes,
|
||||
split_command,
|
||||
split_command, convert_service_networks,
|
||||
)
|
||||
|
||||
|
||||
|
@ -26,11 +26,14 @@ class TaskTemplate(dict):
|
|||
placement (Placement): Placement instructions for the scheduler.
|
||||
If a list is passed instead, it is assumed to be a list of
|
||||
constraints as part of a :py:class:`Placement` object.
|
||||
networks (:py:class:`list`): List of network names or IDs to attach
|
||||
the containers to.
|
||||
force_update (int): A counter that triggers an update even if no
|
||||
relevant parameters have been changed.
|
||||
"""
|
||||
def __init__(self, container_spec, resources=None, restart_policy=None,
|
||||
placement=None, log_driver=None, force_update=None):
|
||||
placement=None, log_driver=None, networks=None,
|
||||
force_update=None):
|
||||
self['ContainerSpec'] = container_spec
|
||||
if resources:
|
||||
self['Resources'] = resources
|
||||
|
@ -42,6 +45,8 @@ class TaskTemplate(dict):
|
|||
self['Placement'] = placement
|
||||
if log_driver:
|
||||
self['LogDriver'] = log_driver
|
||||
if networks:
|
||||
self['Networks'] = convert_service_networks(networks)
|
||||
|
||||
if force_update is not None:
|
||||
if not isinstance(force_update, int):
|
||||
|
|
|
@ -725,7 +725,9 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
version_index = svc_info['Version']['Index']
|
||||
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec, force_update=10)
|
||||
self.client.update_service(name, version_index, task_tmpl, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, task_tmpl, use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
@ -739,7 +741,9 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
name = self.get_service_name()
|
||||
svc_id = self.client.create_service(task_tmpl, name=name, labels={'service.label': 'SampleLabel'})
|
||||
svc_id = self.client.create_service(
|
||||
task_tmpl, name=name, labels={'service.label': 'SampleLabel'}
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
assert 'Labels' in svc_info['Spec']
|
||||
assert 'service.label' in svc_info['Spec']['Labels']
|
||||
|
@ -747,7 +751,10 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
version_index = svc_info['Version']['Index']
|
||||
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec, force_update=10)
|
||||
self.client.update_service(name, version_index, task_tmpl, name=name, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, task_tmpl, name=name,
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
@ -761,8 +768,10 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
name = self.get_service_name()
|
||||
svc_id = self.client.create_service(task_tmpl, name=name,
|
||||
mode=docker.types.ServiceMode(mode='replicated', replicas=2))
|
||||
svc_id = self.client.create_service(
|
||||
task_tmpl, name=name,
|
||||
mode=docker.types.ServiceMode(mode='replicated', replicas=2)
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
assert 'Mode' in svc_info['Spec']
|
||||
assert 'Replicated' in svc_info['Spec']['Mode']
|
||||
|
@ -770,7 +779,10 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
assert svc_info['Spec']['Mode']['Replicated']['Replicas'] == 2
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
self.client.update_service(name, version_index, labels={'force': 'update'}, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, labels={'force': 'update'},
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
@ -786,35 +798,45 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
name = self.get_service_name()
|
||||
svc_id = self.client.create_service(task_tmpl, name=name, labels={'service.label': 'SampleLabel'})
|
||||
svc_id = self.client.create_service(
|
||||
task_tmpl, name=name, labels={'service.label': 'SampleLabel'}
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
assert 'TaskTemplate' in svc_info['Spec']
|
||||
assert 'ContainerSpec' in svc_info['Spec']['TaskTemplate']
|
||||
assert 'Labels' in svc_info['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']['container.label'] == 'SampleLabel'
|
||||
labels = svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']
|
||||
assert labels['container.label'] == 'SampleLabel'
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
self.client.update_service(name, version_index, labels={'force': 'update'}, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, labels={'force': 'update'},
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
assert 'TaskTemplate' in svc_info['Spec']
|
||||
assert 'ContainerSpec' in svc_info['Spec']['TaskTemplate']
|
||||
assert 'Labels' in svc_info['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']['container.label'] == 'SampleLabel'
|
||||
labels = svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']
|
||||
assert labels['container.label'] == 'SampleLabel'
|
||||
|
||||
container_spec = docker.types.ContainerSpec(
|
||||
'busybox', ['echo', 'hello']
|
||||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
self.client.update_service(name, new_index, task_tmpl, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, new_index, task_tmpl, use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
newer_index = svc_info['Version']['Index']
|
||||
assert newer_index > new_index
|
||||
assert 'TaskTemplate' in svc_info['Spec']
|
||||
assert 'ContainerSpec' in svc_info['Spec']['TaskTemplate']
|
||||
assert 'Labels' in svc_info['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']['container.label'] == 'SampleLabel'
|
||||
labels = svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']
|
||||
assert labels['container.label'] == 'SampleLabel'
|
||||
|
||||
def test_update_service_with_defaults_update_config(self):
|
||||
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
|
||||
|
@ -834,7 +856,10 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
assert update_config['FailureAction'] == uc['FailureAction']
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
self.client.update_service(name, version_index, labels={'force': 'update'}, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, labels={'force': 'update'},
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
@ -869,7 +894,10 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
self.client.update_service(name, version_index, labels={'force': 'update'}, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, labels={'force': 'update'},
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
@ -878,7 +906,10 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
{'Target': net1['Id']}, {'Target': net2['Id']}
|
||||
]
|
||||
|
||||
self.client.update_service(name, new_index, networks=[net1['Id']], use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, new_index, networks=[net1['Id']],
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
assert 'Networks' in svc_info['Spec']['TaskTemplate']
|
||||
assert svc_info['Spec']['TaskTemplate']['Networks'] == [
|
||||
|
@ -918,7 +949,10 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
svc_info = self.client.inspect_service(svc_id)
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
self.client.update_service(name, version_index, labels={'force': 'update'}, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, labels={'force': 'update'},
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
@ -968,13 +1002,16 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
self.client.update_service(name, version_index, task_tmpl, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, task_tmpl, use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
container_spec = svc_info['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert (
|
||||
'Healthcheck' not in svc_info['Spec']['TaskTemplate']['ContainerSpec'] or
|
||||
not svc_info['Spec']['TaskTemplate']['ContainerSpec']['Healthcheck']
|
||||
'Healthcheck' not in container_spec or
|
||||
not container_spec['Healthcheck']
|
||||
)
|
||||
|
||||
def test_update_service_remove_labels(self):
|
||||
|
@ -983,14 +1020,18 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
name = self.get_service_name()
|
||||
svc_id = self.client.create_service(task_tmpl, name=name, labels={'service.label': 'SampleLabel'})
|
||||
svc_id = self.client.create_service(
|
||||
task_tmpl, name=name, labels={'service.label': 'SampleLabel'}
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
assert 'Labels' in svc_info['Spec']
|
||||
assert 'service.label' in svc_info['Spec']['Labels']
|
||||
assert svc_info['Spec']['Labels']['service.label'] == 'SampleLabel'
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
self.client.update_service(name, version_index, labels={}, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, labels={}, use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
@ -1003,12 +1044,15 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
name = self.get_service_name()
|
||||
svc_id = self.client.create_service(task_tmpl, name=name, labels={'service.label': 'SampleLabel'})
|
||||
svc_id = self.client.create_service(
|
||||
task_tmpl, name=name, labels={'service.label': 'SampleLabel'}
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
assert 'TaskTemplate' in svc_info['Spec']
|
||||
assert 'ContainerSpec' in svc_info['Spec']['TaskTemplate']
|
||||
assert 'Labels' in svc_info['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']['container.label'] == 'SampleLabel'
|
||||
labels = svc_info['Spec']['TaskTemplate']['ContainerSpec']['Labels']
|
||||
assert labels['container.label'] == 'SampleLabel'
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
container_spec = docker.types.ContainerSpec(
|
||||
|
@ -1016,10 +1060,103 @@ class ServiceTest(BaseAPIIntegrationTest):
|
|||
labels={}
|
||||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
self.client.update_service(name, version_index, task_tmpl, use_current_spec=True)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, task_tmpl, use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
assert 'TaskTemplate' in svc_info['Spec']
|
||||
assert 'ContainerSpec' in svc_info['Spec']['TaskTemplate']
|
||||
assert not svc_info['Spec']['TaskTemplate']['ContainerSpec'].get('Labels')
|
||||
container_spec = svc_info['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert not container_spec.get('Labels')
|
||||
|
||||
@requires_api_version('1.29')
|
||||
def test_update_service_with_network_change(self):
|
||||
container_spec = docker.types.ContainerSpec(
|
||||
'busybox', ['echo', 'hello']
|
||||
)
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
net1 = self.client.create_network(
|
||||
'dockerpytest_1', driver='overlay', ipam={'Driver': 'default'}
|
||||
)
|
||||
self.tmp_networks.append(net1['Id'])
|
||||
net2 = self.client.create_network(
|
||||
'dockerpytest_2', driver='overlay', ipam={'Driver': 'default'}
|
||||
)
|
||||
self.tmp_networks.append(net2['Id'])
|
||||
name = self.get_service_name()
|
||||
svc_id = self.client.create_service(
|
||||
task_tmpl, name=name, networks=[net1['Id']]
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
assert 'Networks' in svc_info['Spec']
|
||||
assert len(svc_info['Spec']['Networks']) > 0
|
||||
assert svc_info['Spec']['Networks'][0]['Target'] == net1['Id']
|
||||
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
task_tmpl = docker.types.TaskTemplate(container_spec)
|
||||
self._update_service(
|
||||
svc_id, name, version_index, task_tmpl, name=name,
|
||||
networks=[net2['Id']], use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
task_template = svc_info['Spec']['TaskTemplate']
|
||||
assert 'Networks' in task_template
|
||||
assert len(task_template['Networks']) > 0
|
||||
assert task_template['Networks'][0]['Target'] == net2['Id']
|
||||
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
assert new_index > version_index
|
||||
|
||||
self._update_service(
|
||||
svc_id, name, new_index, name=name, networks=[net1['Id']],
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
task_template = svc_info['Spec']['TaskTemplate']
|
||||
assert 'ContainerSpec' in task_template
|
||||
new_spec = task_template['ContainerSpec']
|
||||
assert 'Image' in new_spec
|
||||
assert new_spec['Image'].split(':')[0] == 'busybox'
|
||||
assert 'Command' in new_spec
|
||||
assert new_spec['Command'] == ['echo', 'hello']
|
||||
assert 'Networks' in task_template
|
||||
assert len(task_template['Networks']) > 0
|
||||
assert task_template['Networks'][0]['Target'] == net1['Id']
|
||||
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
new_index = svc_info['Version']['Index']
|
||||
|
||||
task_tmpl = docker.types.TaskTemplate(
|
||||
container_spec, networks=[net2['Id']]
|
||||
)
|
||||
self._update_service(
|
||||
svc_id, name, new_index, task_tmpl, name=name,
|
||||
use_current_spec=True
|
||||
)
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
task_template = svc_info['Spec']['TaskTemplate']
|
||||
assert 'Networks' in task_template
|
||||
assert len(task_template['Networks']) > 0
|
||||
assert task_template['Networks'][0]['Target'] == net2['Id']
|
||||
|
||||
def _update_service(self, svc_id, *args, **kwargs):
|
||||
# service update tests seem to be a bit flaky
|
||||
# give them a chance to retry the update with a new version index
|
||||
try:
|
||||
self.client.update_service(*args, **kwargs)
|
||||
except docker.errors.APIError as e:
|
||||
if e.explanation == "update out of sequence":
|
||||
svc_info = self.client.inspect_service(svc_id)
|
||||
version_index = svc_info['Version']['Index']
|
||||
|
||||
if len(args) > 1:
|
||||
args = (args[0], version_index) + args[2:]
|
||||
else:
|
||||
kwargs['version'] = version_index
|
||||
|
||||
self.client.update_service(*args, **kwargs)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import unittest
|
||||
|
||||
import docker
|
||||
import pytest
|
||||
|
||||
from .. import helpers
|
||||
from .base import TEST_API_VERSION
|
||||
|
@ -36,6 +35,25 @@ class ServiceTest(unittest.TestCase):
|
|||
assert "alpine" in container_spec['Image']
|
||||
assert container_spec['Labels'] == {'container': 'label'}
|
||||
|
||||
def test_create_with_network(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
name = helpers.random_name()
|
||||
network = client.networks.create(
|
||||
helpers.random_name(), driver='overlay'
|
||||
)
|
||||
service = client.services.create(
|
||||
# create arguments
|
||||
name=name,
|
||||
# ContainerSpec arguments
|
||||
image="alpine",
|
||||
command="sleep 300",
|
||||
networks=[network.id]
|
||||
)
|
||||
assert 'Networks' in service.attrs['Spec']['TaskTemplate']
|
||||
networks = service.attrs['Spec']['TaskTemplate']['Networks']
|
||||
assert len(networks) == 1
|
||||
assert networks[0]['Target'] == network.id
|
||||
|
||||
def test_get(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
name = helpers.random_name()
|
||||
|
@ -82,7 +100,6 @@ class ServiceTest(unittest.TestCase):
|
|||
assert len(tasks) == 1
|
||||
assert tasks[0]['ServiceID'] == service2.id
|
||||
|
||||
@pytest.mark.skip(reason="Makes Swarm unstable?")
|
||||
def test_update(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
service = client.services.create(
|
||||
|
@ -101,3 +118,105 @@ class ServiceTest(unittest.TestCase):
|
|||
service.reload()
|
||||
container_spec = service.attrs['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert container_spec['Command'] == ["sleep", "600"]
|
||||
|
||||
def test_update_retains_service_labels(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
service = client.services.create(
|
||||
# create arguments
|
||||
name=helpers.random_name(),
|
||||
labels={'service.label': 'SampleLabel'},
|
||||
# ContainerSpec arguments
|
||||
image="alpine",
|
||||
command="sleep 300"
|
||||
)
|
||||
service.update(
|
||||
# create argument
|
||||
name=service.name,
|
||||
# ContainerSpec argument
|
||||
command="sleep 600"
|
||||
)
|
||||
service.reload()
|
||||
labels = service.attrs['Spec']['Labels']
|
||||
assert labels == {'service.label': 'SampleLabel'}
|
||||
|
||||
def test_update_retains_container_labels(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
service = client.services.create(
|
||||
# create arguments
|
||||
name=helpers.random_name(),
|
||||
# ContainerSpec arguments
|
||||
image="alpine",
|
||||
command="sleep 300",
|
||||
container_labels={'container.label': 'SampleLabel'}
|
||||
)
|
||||
service.update(
|
||||
# create argument
|
||||
name=service.name,
|
||||
# ContainerSpec argument
|
||||
command="sleep 600"
|
||||
)
|
||||
service.reload()
|
||||
container_spec = service.attrs['Spec']['TaskTemplate']['ContainerSpec']
|
||||
assert container_spec['Labels'] == {'container.label': 'SampleLabel'}
|
||||
|
||||
def test_update_remove_service_labels(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
service = client.services.create(
|
||||
# create arguments
|
||||
name=helpers.random_name(),
|
||||
labels={'service.label': 'SampleLabel'},
|
||||
# ContainerSpec arguments
|
||||
image="alpine",
|
||||
command="sleep 300"
|
||||
)
|
||||
service.update(
|
||||
# create argument
|
||||
name=service.name,
|
||||
labels={},
|
||||
# ContainerSpec argument
|
||||
command="sleep 600"
|
||||
)
|
||||
service.reload()
|
||||
assert not service.attrs['Spec'].get('Labels')
|
||||
|
||||
def test_scale_service(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
service = client.services.create(
|
||||
# create arguments
|
||||
name=helpers.random_name(),
|
||||
# ContainerSpec arguments
|
||||
image="alpine",
|
||||
command="sleep 300"
|
||||
)
|
||||
assert len(service.tasks()) == 1
|
||||
service.update(
|
||||
# create argument
|
||||
name=service.name,
|
||||
mode=docker.types.ServiceMode('replicated', replicas=2),
|
||||
# ContainerSpec argument
|
||||
command="sleep 600"
|
||||
)
|
||||
service.reload()
|
||||
assert len(service.tasks()) >= 2
|
||||
|
||||
@helpers.requires_api_version('1.25')
|
||||
def test_restart_service(self):
|
||||
client = docker.from_env(version=TEST_API_VERSION)
|
||||
service = client.services.create(
|
||||
# create arguments
|
||||
name=helpers.random_name(),
|
||||
# ContainerSpec arguments
|
||||
image="alpine",
|
||||
command="sleep 300"
|
||||
)
|
||||
initial_version = service.version
|
||||
service.update(
|
||||
# create argument
|
||||
name=service.name,
|
||||
# task template argument
|
||||
force_update=10,
|
||||
# ContainerSpec argument
|
||||
command="sleep 600"
|
||||
)
|
||||
service.reload()
|
||||
assert service.version > initial_version
|
||||
|
|
|
@ -35,18 +35,18 @@ class CreateServiceKwargsTest(unittest.TestCase):
|
|||
'labels': {'key': 'value'},
|
||||
'mode': 'global',
|
||||
'update_config': {'update': 'config'},
|
||||
'networks': ['somenet'],
|
||||
'endpoint_spec': {'blah': 'blah'},
|
||||
}
|
||||
assert set(task_template.keys()) == set([
|
||||
'ContainerSpec', 'Resources', 'RestartPolicy', 'Placement',
|
||||
'LogDriver'
|
||||
'LogDriver', 'Networks'
|
||||
])
|
||||
assert task_template['Placement'] == {'Constraints': ['foo=bar']}
|
||||
assert task_template['LogDriver'] == {
|
||||
'Name': 'logdriver',
|
||||
'Options': {'foo': 'bar'}
|
||||
}
|
||||
assert task_template['Networks'] == [{'Target': 'somenet'}]
|
||||
assert set(task_template['ContainerSpec'].keys()) == set([
|
||||
'Image', 'Command', 'Args', 'Hostname', 'Env', 'Dir', 'User',
|
||||
'Labels', 'Mounts', 'StopGracePeriod'
|
||||
|
|
Loading…
Reference in New Issue