From edb9e3c2ae85f382549df8365a5b2f18986fc5e2 Mon Sep 17 00:00:00 2001 From: Felipe Ruhland Date: Thu, 21 Dec 2017 23:13:18 -0200 Subject: [PATCH 1/3] Added scale method to the Service model. Signed-off-by: Felipe Ruhland --- docker/models/services.py | 18 +++++++++++++++++- tests/integration/models_services_test.py | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/docker/models/services.py b/docker/models/services.py index 009e4551ac..e87e2d43ad 100644 --- a/docker/models/services.py +++ b/docker/models/services.py @@ -1,6 +1,6 @@ import copy from docker.errors import create_unexpected_kwargs_error -from docker.types import TaskTemplate, ContainerSpec +from docker.types import TaskTemplate, ContainerSpec, ServiceMode from .resource import Model, Collection @@ -105,6 +105,22 @@ def logs(self, **kwargs): ) return self.client.api.service_logs(self.id, is_tty=is_tty, **kwargs) + def scale(self, replicas): + """ + Scale service container. + + Args: + replicas (int): The number of containers that should be running. + + Returns: + ``True``if successful. + """ + + service_mode = ServiceMode('replicated', replicas) + return self.client.api.update_service(self.id, self.version, + service_mode, + fetch_current_spec=True) + class ServiceCollection(Collection): """Services on the Docker server.""" diff --git a/tests/integration/models_services_test.py b/tests/integration/models_services_test.py index ca8be48de4..e7f16cdff2 100644 --- a/tests/integration/models_services_test.py +++ b/tests/integration/models_services_test.py @@ -203,6 +203,28 @@ def test_scale_service(self): spec = service.attrs['Spec']['TaskTemplate']['ContainerSpec'] assert spec.get('Command') == ['sleep', '300'] + def test_scale_method_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" + ) + tasks = [] + while len(tasks) == 0: + tasks = service.tasks() + assert len(tasks) == 1 + service.scale(2) + while len(tasks) == 1: + tasks = service.tasks() + assert len(tasks) >= 2 + # check that the container spec is not overridden with None + service.reload() + spec = service.attrs['Spec']['TaskTemplate']['ContainerSpec'] + assert spec.get('Command') == ['sleep', '300'] + @helpers.requires_api_version('1.25') def test_restart_service(self): client = docker.from_env(version=TEST_API_VERSION) From 0e0a8526801d207bfdf2e9011ab1348525437a79 Mon Sep 17 00:00:00 2001 From: Felipe Ruhland Date: Tue, 26 Dec 2017 18:25:20 -0200 Subject: [PATCH 2/3] Ensure that global containers are not scaled Signed-off-by: Felipe Ruhland --- docker/models/services.py | 5 ++++- tests/integration/models_services_test.py | 24 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docker/models/services.py b/docker/models/services.py index e87e2d43ad..4c8accefdb 100644 --- a/docker/models/services.py +++ b/docker/models/services.py @@ -1,5 +1,5 @@ import copy -from docker.errors import create_unexpected_kwargs_error +from docker.errors import create_unexpected_kwargs_error, InvalidArgument from docker.types import TaskTemplate, ContainerSpec, ServiceMode from .resource import Model, Collection @@ -116,6 +116,9 @@ def scale(self, replicas): ``True``if successful. """ + if not self.attrs['Spec']['Mode'].get('Global'): + raise InvalidArgument('Cannot scale a global container') + service_mode = ServiceMode('replicated', replicas) return self.client.api.update_service(self.id, self.version, service_mode, diff --git a/tests/integration/models_services_test.py b/tests/integration/models_services_test.py index e7f16cdff2..64aba66e95 100644 --- a/tests/integration/models_services_test.py +++ b/tests/integration/models_services_test.py @@ -4,6 +4,8 @@ from .. import helpers from .base import TEST_API_VERSION +from docker.errors import InvalidArgument +from docker.models.services import ServiceMode class ServiceTest(unittest.TestCase): @@ -225,6 +227,28 @@ def test_scale_method_service(self): spec = service.attrs['Spec']['TaskTemplate']['ContainerSpec'] assert spec.get('Command') == ['sleep', '300'] + def test_scale_method_global_service(self): + client = docker.from_env(version=TEST_API_VERSION) + mode = ServiceMode('global') + service = client.services.create( + name=helpers.random_name(), + image="alpine", + command="sleep 300", + mode=mode + ) + tasks = [] + while len(tasks) == 0: + tasks = service.tasks() + assert len(tasks) == 1 + with self.assertRaises(InvalidArgument, + msg='Cannot scale a global container'): + service.scale(2) + + assert len(tasks) == 1 + service.reload() + spec = service.attrs['Spec']['TaskTemplate']['ContainerSpec'] + assert spec.get('Command') == ['sleep', '300'] + @helpers.requires_api_version('1.25') def test_restart_service(self): client = docker.from_env(version=TEST_API_VERSION) From 663c6089e962f024eafad7fb5bcf88847dd8b28a Mon Sep 17 00:00:00 2001 From: Felipe Ruhland Date: Tue, 2 Jan 2018 22:46:17 -0200 Subject: [PATCH 3/3] Fix test to make sure the initial mode is replicated Signed-off-by: Felipe Ruhland --- docker/models/services.py | 2 +- tests/integration/models_services_test.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/models/services.py b/docker/models/services.py index 4c8accefdb..337ed44460 100644 --- a/docker/models/services.py +++ b/docker/models/services.py @@ -116,7 +116,7 @@ def scale(self, replicas): ``True``if successful. """ - if not self.attrs['Spec']['Mode'].get('Global'): + if 'Global' in self.attrs['Spec']['Mode'].keys(): raise InvalidArgument('Cannot scale a global container') service_mode = ServiceMode('replicated', replicas) diff --git a/tests/integration/models_services_test.py b/tests/integration/models_services_test.py index 64aba66e95..15b87da494 100644 --- a/tests/integration/models_services_test.py +++ b/tests/integration/models_services_test.py @@ -5,7 +5,7 @@ from .. import helpers from .base import TEST_API_VERSION from docker.errors import InvalidArgument -from docker.models.services import ServiceMode +from docker.types.services import ServiceMode class ServiceTest(unittest.TestCase): @@ -212,7 +212,7 @@ def test_scale_method_service(self): name=helpers.random_name(), # ContainerSpec arguments image="alpine", - command="sleep 300" + command="sleep 300", ) tasks = [] while len(tasks) == 0: