Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement cap_add and cap_drop handling for docker_swarm_service #294

Merged
merged 7 commits into from
Feb 12, 2022
2 changes: 2 additions & 0 deletions changelogs/fragments/271-swarm-service-capabilities.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changs:
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
- docker_swarm_service - add support for setting capabilities with the ``cap_add`` and ``cap_drop`` parameters. Usage is the same as with the ``capabilities`` and ``cap_drop`` parameters for ``docker_container`` (https://github.com/ansible-collections/community.docker/pull/294)
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
32 changes: 32 additions & 0 deletions plugins/modules/docker_swarm_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,18 @@
- Path to the working directory.
- Corresponds to the C(--workdir) option of C(docker service create).
type: str
cap_add:
description:
- List of capabilities to add to the container.
- Requires API version >= 1.41.
type: list
elements: str
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
cap_drop:
description:
- List of capabilities to drop from the container.
- Requires API version >= 1.41.
type: list
elements: str
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
extends_documentation_fragment:
- community.docker.docker
- community.docker.docker.docker_py_2_documentation
Expand Down Expand Up @@ -1240,6 +1252,8 @@ def __init__(self, docker_api_version, docker_py_version):
self.update_order = None
self.working_dir = None
self.init = None
self.cap_add = None
self.cap_drop = None

self.docker_api_version = docker_api_version
self.docker_py_version = docker_py_version
Expand Down Expand Up @@ -1296,6 +1310,8 @@ def get_facts(self):
'user': self.user,
'working_dir': self.working_dir,
'init': self.init,
'cap_add': self.cap_add,
'cap_drop': self.cap_drop,
}

@property
Expand Down Expand Up @@ -1525,6 +1541,8 @@ def from_ansible_params(
s.working_dir = ap['working_dir']
s.read_only = ap['read_only']
s.init = ap['init']
s.cap_add = ap['cap_add']
s.cap_drop = ap['cap_drop']

s.networks = get_docker_networks(ap['networks'], network_ids)

Expand Down Expand Up @@ -1773,6 +1791,10 @@ def compare(self, os):
force_update = True
if self.init is not None and self.init != os.init:
differences.add('init', parameter=self.init, active=os.init)
if self.cap_add is not None and self.cap_add != os.cap_add:
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
differences.add('cap_add', parameter=self.cap_add, active=os.cap_add)
if self.cap_drop is not None and self.cap_drop != os.cap_drop:
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
differences.add('cap_drop', parameter=self.cap_drop, active=os.cap_drop)
return not differences.empty or force_update, differences, needs_rebuild, force_update

def has_healthcheck_changed(self, old_publish):
Expand Down Expand Up @@ -1938,6 +1960,10 @@ def build_container_spec(self):
container_spec_args['configs'] = configs
if self.init is not None:
container_spec_args['init'] = self.init
if self.cap_add is not None:
container_spec_args['cap_add'] = self.cap_add
if self.cap_drop is not None:
container_spec_args['cap_drop'] = self.cap_drop

return types.ContainerSpec(self.image, **container_spec_args)

Expand Down Expand Up @@ -2131,6 +2157,8 @@ def get_service(self, name):
ds.stop_signal = task_template_data['ContainerSpec'].get('StopSignal')
ds.working_dir = task_template_data['ContainerSpec'].get('Dir')
ds.read_only = task_template_data['ContainerSpec'].get('ReadOnly')
ds.cap_add = task_template_data['ContainerSpec'].get('CapabilityAdd')
ds.cap_drop = task_template_data['ContainerSpec'].get('CapabilityDrop')

healthcheck_data = task_template_data['ContainerSpec'].get('Healthcheck')
if healthcheck_data:
Expand Down Expand Up @@ -2694,6 +2722,8 @@ def main():
user=dict(type='str'),
working_dir=dict(type='str'),
init=dict(type='bool'),
cap_add=dict(type='list', elements='str'),
cap_drop=dict(type='list', elements='str'),
)

option_minimal_versions = dict(
Expand All @@ -2715,6 +2745,8 @@ def main():
resolve_image=dict(docker_api_version='1.30', docker_py_version='3.2.0'),
rollback_config=dict(docker_py_version='3.5.0', docker_api_version='1.28'),
init=dict(docker_py_version='4.0.0', docker_api_version='1.37'),
cap_add=dict(docker_py_version='5.0.3', docker_api_version='1.41'),
cap_drop=dict(docker_py_version='5.0.3', docker_api_version='1.41'),
# specials
publish_mode=dict(
docker_py_version='3.0.0',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1920,3 +1920,79 @@
- init_1 is failed
- "('version is ' ~ docker_api_version ~'. Minimum version required is 1.37') in hosts_1.msg"
when: docker_api_version is version('1.37', '<')

####################################################################
## cap_drop, capabilities ##########################################
####################################################################

- name: capabilities, cap_drop
docker_swarm_service:
name: "{{ service_name }}"
image: "{{ docker_test_image_alpine }}"
resolve_image: no
init: true
cap_add:
- sys_time
cap_drop:
- all
register: capabilities_1
ignore_errors: yes

- name: capabilities, cap_drop (idempotency)
docker_swarm_service:
name: "{{ service_name }}"
image: "{{ docker_test_image_alpine }}"
resolve_image: no
init: true
cap_add:
- sys_time
cap_drop:
- all
register: capabilities_2
ignore_errors: yes

- name: capabilities, cap_drop (less)
docker_swarm_service:
name: "{{ service_name }}"
image: "{{ docker_test_image_alpine }}"
resolve_image: no
init: true
cap_add: []
cap_drop:
- all
register: capabilities_3
ignore_errors: yes

- name: capabilities, cap_drop (changed)
docker_swarm_service:
name: "{{ service_name }}"
image: "{{ docker_test_image_alpine }}"
resolve_image: no
init: true
cap_add:
- setgid
cap_drop:
- all
register: capabilities_4
ignore_errors: yes

- name: cleanup
docker_swarm_service:
name: "{{ service_name }}"
state: absent
diff: no

- assert:
that:
- capabilities_1 is changed
- capabilities_2 is not changed
- capabilities_3 is not changed
- capabilities_4 is changed
when: docker_py_version is version('5.0.3', '>=')
felixfontein marked this conversation as resolved.
Show resolved Hide resolved

- assert:
that:
- capabilities_1 is failed
- "('version is ' ~ docker_py_version ~ ' ') in capabilities_1.msg"
- "'Minimum version required is 5.0.3 ' in capabilities_1.msg"
andrasmaroy marked this conversation as resolved.
Show resolved Hide resolved
when: docker_py_version is version('5.0.3', '<')
2 changes: 2 additions & 0 deletions tests/integration/targets/docker_swarm_service/vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

service_expected_output:
args: [sleep, '1800']
cap_add: null
cap_drop: null
configs: null
constraints: null
container_labels: null
Expand Down