Skip to content

Commit

Permalink
swarm: add sysctl support for services (#3029)
Browse files Browse the repository at this point in the history
Signed-off-by: Quentin Mathorel <[email protected]>
  • Loading branch information
Aadenei authored Aug 12, 2022
1 parent ff0b4ac commit 58aa62b
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
3 changes: 3 additions & 0 deletions docker/models/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ def create(self, image, command=None, **kwargs):
the default set for the container.
cap_drop (:py:class:`list`): A list of kernel capabilities to drop
from the default set for the container.
sysctls (:py:class:`dict`): A dict of sysctl values to add to the
container
Returns:
:py:class:`Service`: The created service.
Expand Down Expand Up @@ -305,6 +307,7 @@ def list(self, **kwargs):
'tty',
'user',
'workdir',
'sysctls',
]

# kwargs to copy straight over to TaskTemplate
Expand Down
10 changes: 9 additions & 1 deletion docker/types/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class ContainerSpec(dict):
default set for the container.
cap_drop (:py:class:`list`): A list of kernel capabilities to drop from
the default set for the container.
sysctls (:py:class:`dict`): A dict of sysctl values to add to
the container
"""

def __init__(self, image, command=None, args=None, hostname=None, env=None,
Expand All @@ -123,7 +125,7 @@ def __init__(self, image, command=None, args=None, hostname=None, env=None,
open_stdin=None, read_only=None, stop_signal=None,
healthcheck=None, hosts=None, dns_config=None, configs=None,
privileges=None, isolation=None, init=None, cap_add=None,
cap_drop=None):
cap_drop=None, sysctls=None):
self['Image'] = image

if isinstance(command, str):
Expand Down Expand Up @@ -205,6 +207,12 @@ def __init__(self, image, command=None, args=None, hostname=None, env=None,

self['CapabilityDrop'] = cap_drop

if sysctls is not None:
if not isinstance(sysctls, dict):
raise TypeError('sysctls must be a dict')

self['Sysctls'] = sysctls


class Mount(dict):
"""
Expand Down
20 changes: 20 additions & 0 deletions tests/integration/api_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1419,3 +1419,23 @@ def test_create_service_cap_drop(self):
assert services[0]['ID'] == svc_id['ID']
spec = services[0]['Spec']['TaskTemplate']['ContainerSpec']
assert 'CAP_SYSLOG' in spec['CapabilityDrop']

@requires_api_version('1.40')
def test_create_service_with_sysctl(self):
name = self.get_service_name()
sysctls = {
'net.core.somaxconn': '1024',
'net.ipv4.tcp_syncookies': '0',
}
container_spec = docker.types.ContainerSpec(
TEST_IMG, ['echo', 'hello'], sysctls=sysctls
)
task_tmpl = docker.types.TaskTemplate(container_spec)
svc_id = self.client.create_service(task_tmpl, name=name)
assert self.client.inspect_service(svc_id)
services = self.client.services(filters={'name': name})
assert len(services) == 1
assert services[0]['ID'] == svc_id['ID']
spec = services[0]['Spec']['TaskTemplate']['ContainerSpec']
assert spec['Sysctls']['net.core.somaxconn'] == '1024'
assert spec['Sysctls']['net.ipv4.tcp_syncookies'] == '0'
5 changes: 3 additions & 2 deletions tests/unit/models_services_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ def test_get_create_service_kwargs(self):
'constraints': ['foo=bar'],
'preferences': ['bar=baz'],
'platforms': [('x86_64', 'linux')],
'maxreplicas': 1
'maxreplicas': 1,
'sysctls': {'foo': 'bar'}
})

task_template = kwargs.pop('task_template')
Expand Down Expand Up @@ -59,5 +60,5 @@ def test_get_create_service_kwargs(self):
assert task_template['Networks'] == [{'Target': 'somenet'}]
assert set(task_template['ContainerSpec'].keys()) == {
'Image', 'Command', 'Args', 'Hostname', 'Env', 'Dir', 'User',
'Labels', 'Mounts', 'StopGracePeriod'
'Labels', 'Mounts', 'StopGracePeriod', 'Sysctls'
}

0 comments on commit 58aa62b

Please sign in to comment.