Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions docker/api/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from ..types import ServiceMode


def _check_api_features(version, task_template, update_config, endpoint_spec):
def _check_api_features(version, task_template, update_config, endpoint_spec,
rollback_config):

def raise_version_error(param, min_version):
raise errors.InvalidVersion(
Expand All @@ -28,6 +29,14 @@ def raise_version_error(param, min_version):
if 'Order' in update_config:
raise_version_error('UpdateConfig.order', '1.29')

if rollback_config is not None:
if utils.version_lt(version, '1.28'):
raise_version_error('rollback_config', '1.28')

if utils.version_lt(version, '1.29'):
if 'Order' in update_config:
raise_version_error('RollbackConfig.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']):
Expand Down Expand Up @@ -105,7 +114,7 @@ class ServiceApiMixin(object):
def create_service(
self, task_template, name=None, labels=None, mode=None,
update_config=None, networks=None, endpoint_config=None,
endpoint_spec=None
endpoint_spec=None, rollback_config=None
):
"""
Create a service.
Expand All @@ -120,6 +129,8 @@ def create_service(
or global). Defaults to replicated.
update_config (UpdateConfig): Specification for the update strategy
of the service. Default: ``None``
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
networks (:py:class:`list`): List of network names or IDs to attach
the service to. Default: ``None``.
endpoint_spec (EndpointSpec): Properties that can be configured to
Expand All @@ -135,7 +146,8 @@ def create_service(
"""

_check_api_features(
self._version, task_template, update_config, endpoint_spec
self._version, task_template, update_config, endpoint_spec,
rollback_config
)

url = self._url('/services/create')
Expand Down Expand Up @@ -166,6 +178,9 @@ def create_service(
if update_config is not None:
data['UpdateConfig'] = update_config

if rollback_config is not None:
data['RollbackConfig'] = rollback_config

return self._result(
self._post_json(url, data=data, headers=headers), True
)
Expand Down Expand Up @@ -342,7 +357,8 @@ def tasks(self, filters=None):
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, fetch_current_spec=False):
endpoint_spec=None, fetch_current_spec=False,
rollback_config=None):
"""
Update a service.

Expand All @@ -360,6 +376,8 @@ def update_service(self, service, version, task_template=None, name=None,
or global). Defaults to replicated.
update_config (UpdateConfig): Specification for the update strategy
of the service. Default: ``None``.
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
networks (:py:class:`list`): List of network names or IDs to attach
the service to. Default: ``None``.
endpoint_spec (EndpointSpec): Properties that can be configured to
Expand All @@ -376,7 +394,8 @@ def update_service(self, service, version, task_template=None, name=None,
"""

_check_api_features(
self._version, task_template, update_config, endpoint_spec
self._version, task_template, update_config, endpoint_spec,
rollback_config
)

if fetch_current_spec:
Expand Down Expand Up @@ -422,6 +441,11 @@ def update_service(self, service, version, task_template=None, name=None,
else:
data['UpdateConfig'] = current.get('UpdateConfig')

if rollback_config is not None:
data['RollbackConfig'] = rollback_config
else:
data['RollbackConfig'] = current.get('RollbackConfig')

if networks is not None:
converted_networks = utils.convert_service_networks(networks)
if utils.version_lt(self._version, '1.25'):
Expand Down
2 changes: 2 additions & 0 deletions docker/models/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ def create(self, image, command=None, **kwargs):
containers to terminate before forcefully killing them.
update_config (UpdateConfig): Specification for the update strategy
of the service. Default: ``None``
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
user (str): User to run commands as.
workdir (str): Working directory for commands to run.
tty (boolean): Whether a pseudo-TTY should be allocated.
Expand Down
4 changes: 2 additions & 2 deletions docker/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .networks import EndpointConfig, IPAMConfig, IPAMPool, NetworkingConfig
from .services import (
ConfigReference, ContainerSpec, DNSConfig, DriverConfig, EndpointSpec,
Mount, Placement, Privileges, Resources, RestartPolicy, SecretReference,
ServiceMode, TaskTemplate, UpdateConfig
Mount, Placement, Privileges, Resources, RestartPolicy, RollbackConfig,
SecretReference, ServiceMode, TaskTemplate, UpdateConfig
)
from .swarm import SwarmSpec, SwarmExternalCA
24 changes: 24 additions & 0 deletions docker/types/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,30 @@ def __init__(self, parallelism=0, delay=None, failure_action='continue',
self['Order'] = order


class RollbackConfig(UpdateConfig):
"""
Used to specify the way containe rollbacks should be performed by a service

Args:
parallelism (int): Maximum number of tasks to be rolled back in one
iteration (0 means unlimited parallelism). Default: 0
delay (int): Amount of time between rollbacks, in nanoseconds.
failure_action (string): Action to take if a rolled back task fails to
run, or stops running during the rollback. Acceptable values are
``continue``, ``pause`` or ``rollback``.
Default: ``continue``
monitor (int): Amount of time to monitor each rolled back task for
failures, in nanoseconds.
max_failure_ratio (float): The fraction of tasks that may fail during
a rollback before the failure action is invoked, specified as a
floating point number between 0 and 1. Default: 0
order (string): Specifies the order of operations when rolling out a
rolled back task. Either ``start_first`` or ``stop_first`` are
accepted.
"""
pass


class RestartConditionTypesEnum(object):
_values = (
'none',
Expand Down
21 changes: 21 additions & 0 deletions tests/integration/api_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,27 @@ def test_create_service_with_update_config_monitor(self):
assert update_config['Monitor'] == uc['Monitor']
assert update_config['MaxFailureRatio'] == uc['MaxFailureRatio']

@requires_api_version('1.28')
def test_create_service_with_rollback_config(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec)
rollback_cfg = docker.types.RollbackConfig(
parallelism=10, delay=5, failure_action='pause',
monitor=300000000, max_failure_ratio=0.4
)
name = self.get_service_name()
svc_id = self.client.create_service(
task_tmpl, rollback_config=rollback_cfg, name=name
)
svc_info = self.client.inspect_service(svc_id)
assert 'RollbackConfig' in svc_info['Spec']
rc = svc_info['Spec']['RollbackConfig']
assert rollback_cfg['Parallelism'] == rc['Parallelism']
assert rollback_cfg['Delay'] == rc['Delay']
assert rollback_cfg['FailureAction'] == rc['FailureAction']
assert rollback_cfg['Monitor'] == rc['Monitor']
assert rollback_cfg['MaxFailureRatio'] == rc['MaxFailureRatio']

def test_create_service_with_restart_policy(self):
container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
policy = docker.types.RestartPolicy(
Expand Down