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
23 changes: 21 additions & 2 deletions docker/models/services.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import copy
from docker.errors import create_unexpected_kwargs_error
from docker.types import TaskTemplate, ContainerSpec
from docker.errors import create_unexpected_kwargs_error, InvalidArgument
from docker.types import TaskTemplate, ContainerSpec, ServiceMode
from .resource import Model, Collection


Expand Down Expand Up @@ -105,6 +105,25 @@ 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.
"""

if 'Global' in self.attrs['Spec']['Mode'].keys():
raise InvalidArgument('Cannot scale a global container')

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."""
Expand Down
46 changes: 46 additions & 0 deletions tests/integration/models_services_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from .. import helpers
from .base import TEST_API_VERSION
from docker.errors import InvalidArgument
from docker.types.services import ServiceMode


class ServiceTest(unittest.TestCase):
Expand Down Expand Up @@ -203,6 +205,50 @@ def test_scale_service(self):
spec = service.attrs['Spec']['TaskTemplate']['ContainerSpec']
assert spec.get('Command') == ['sleep', '300']

def test_scale_method_service(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is failing because the default mode for a service is global. Make sure to set the initial mode to replicated!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @shin-. I already changed.

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']

def test_scale_method_global_service(self):
client = docker.from_env(version=TEST_API_VERSION)
mode = ServiceMode('global')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the default value is replicated.

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)
Expand Down