diff options
Diffstat (limited to 'docker/api/service.py')
| -rw-r--r-- | docker/api/service.py | 81 |
1 files changed, 67 insertions, 14 deletions
diff --git a/docker/api/service.py b/docker/api/service.py index 4c10ef8..86f4b07 100644 --- a/docker/api/service.py +++ b/docker/api/service.py @@ -19,6 +19,10 @@ def _check_api_features(version, task_template, update_config): if 'Monitor' in update_config: raise_version_error('UpdateConfig.monitor', '1.25') + if utils.version_lt(version, '1.29'): + if 'Order' in update_config: + raise_version_error('UpdateConfig.order', '1.29') + if task_template is not None: if 'ForceUpdate' in task_template and utils.version_lt( version, '1.25'): @@ -62,6 +66,21 @@ def _check_api_features(version, task_template, update_config): raise_version_error('ContainerSpec.privileges', '1.30') +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(): + if cs_value is not None: + merged['ContainerSpec'][cs_key] = cs_value + elif ts_value is not None: + merged[ts_key] = ts_value + return merged + + class ServiceApiMixin(object): @utils.minimum_version('1.24') def create_service( @@ -306,7 +325,7 @@ class ServiceApiMixin(object): def update_service(self, service, version, task_template=None, name=None, labels=None, mode=None, update_config=None, networks=None, endpoint_config=None, - endpoint_spec=None): + endpoint_spec=None, fetch_current_spec=False): """ Update a service. @@ -328,6 +347,8 @@ class ServiceApiMixin(object): the service to. Default: ``None``. endpoint_spec (EndpointSpec): Properties that can be configured to access and load balance a service. Default: ``None``. + fetch_current_spec (boolean): Use the undefined settings from the + current specification of the service. Default: ``False`` Returns: ``True`` if successful. @@ -345,32 +366,64 @@ class ServiceApiMixin(object): _check_api_features(self._version, task_template, update_config) + if fetch_current_spec: + inspect_defaults = True + if utils.version_lt(self._version, '1.29'): + inspect_defaults = None + current = self.inspect_service( + service, insert_defaults=inspect_defaults + )['Spec'] + + else: + current = {} + url = self._url('/services/{0}/update', service) data = {} headers = {} - if name is not None: - data['Name'] = name - if labels is not None: - data['Labels'] = labels + + data['Name'] = current.get('Name') if name is None else name + + data['Labels'] = current.get('Labels') if labels is None else labels + if mode is not None: if not isinstance(mode, dict): mode = ServiceMode(mode) data['Mode'] = mode - if task_template is not None: - image = 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'] = task_template + else: + data['Mode'] = current.get('Mode') + + data['TaskTemplate'] = _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 + else: + data['UpdateConfig'] = current.get('UpdateConfig') if networks is not None: - data['Networks'] = utils.convert_service_networks(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 + else: + data['EndpointSpec'] = current.get('EndpointSpec') resp = self._post_json( url, data=data, params={'version': version}, headers=headers |
