Skip to content

Commit

Permalink
Replicas max per node (#92)
Browse files Browse the repository at this point in the history
* Adding 'replicas_max_per_node' placement parameter

* Adding 'replicas_max_per_node' placement parameter

* Adding 'replicas_max_per_node' integration tests

* Adding 'replicas_max_per_node' feature

* 'replicas_max_per_node' documentation update

* 'replicas_max_per_node' unit test fix

* Documentation and changelog updates

* Update changelogs/fragments/92-replicas-max-per-node.yml

Co-authored-by: Felix Fontein <[email protected]>

Co-authored-by: WojciechowskiPiotr <[email protected]>
Co-authored-by: Felix Fontein <[email protected]>
  • Loading branch information
3 people authored Feb 24, 2021
1 parent f5d6875 commit 3ddd75a
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/92-replicas-max-per-node.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- "docker_swarm_service - adding support for maximum number of tasks per node (``replicas_max_per_node``) when running swarm service in replicated mode. Introduced in API 1.40 (https://github.com/ansible-collections/community.docker/issues/7, https://github.com/ansible-collections/community.docker/pull/92)."
32 changes: 32 additions & 0 deletions plugins/modules/docker_swarm_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- "Dario Zanzico (@dariko)"
- "Jason Witkowski (@jwitko)"
- "Hannes Ljungberg (@hannseman)"
- "Piotr Wojciechowski (@wojciechowskipiotr)"
short_description: docker swarm service
description:
- Manages docker services via a swarm manager node.
Expand Down Expand Up @@ -344,6 +345,13 @@
- Requires API version >= 1.27.
type: list
elements: dict
replicas_max_per_node:
description:
- Maximum number of tasks per node.
- Corresponds to the C(--replicas_max_per_node) option of C(docker service create).
- Requires API version >= 1.40
type: int
version_added: 1.3.0
type: dict
publish:
description:
Expand Down Expand Up @@ -718,6 +726,7 @@
"publish": null,
"read_only": null,
"replicas": 1,
"replicas_max_per_node": 1,
"reserve_cpu": 0.25,
"reserve_memory": 20971520,
"restart_policy": "on-failure",
Expand Down Expand Up @@ -840,6 +849,7 @@
constraints:
- node.role == manager
- engine.labels.operatingsystem == ubuntu 14.04
replicas_max_per_node: 2
- name: Set configs
community.docker.docker_swarm_service:
Expand Down Expand Up @@ -1208,6 +1218,7 @@ def __init__(self, docker_api_version, docker_py_version):
self.configs = None
self.secrets = None
self.constraints = None
self.replicas_max_per_node = None
self.networks = None
self.stop_grace_period = None
self.stop_signal = None
Expand Down Expand Up @@ -1257,6 +1268,7 @@ def get_facts(self):
'log_driver_options': self.log_driver_options,
'publish': self.publish,
'constraints': self.constraints,
'replicas_max_per_node': self.replicas_max_per_node,
'placement_preferences': self.placement_preferences,
'labels': self.labels,
'container_labels': self.container_labels,
Expand Down Expand Up @@ -1472,9 +1484,15 @@ def get_placement_from_ansible_params(params):
)

preferences = placement.get('preferences')
replicas_max_per_node = get_value(
'replicas_max_per_node',
placement
)

return {
'constraints': constraints,
'placement_preferences': preferences,
'replicas_max_per_node': replicas_max_per_node,
}

@classmethod
Expand Down Expand Up @@ -1683,6 +1701,8 @@ def compare(self, os):
differences.add('args', parameter=self.args, active=os.args)
if has_list_changed(self.constraints, os.constraints):
differences.add('constraints', parameter=self.constraints, active=os.constraints)
if self.replicas_max_per_node is not None and self.replicas_max_per_node != os.replicas_max_per_node:
differences.add('replicas_max_per_node', parameter=self.replicas_max_per_node, active=os.replicas_max_per_node)
if has_list_changed(self.placement_preferences, os.placement_preferences, sort_lists=False):
differences.add('placement_preferences', parameter=self.placement_preferences, active=os.placement_preferences)
if has_list_changed(self.groups, os.groups):
Expand Down Expand Up @@ -1923,6 +1943,8 @@ def build_placement(self):
placement_args = {}
if self.constraints is not None:
placement_args['constraints'] = self.constraints
if self.replicas_max_per_node is not None:
placement_args['maxreplicas'] = self.replicas_max_per_node
if self.placement_preferences is not None:
placement_args['preferences'] = [
{key.title(): {'SpreadDescriptor': value}}
Expand Down Expand Up @@ -2164,6 +2186,7 @@ def get_service(self, name):
placement = task_template_data.get('Placement')
if placement:
ds.constraints = placement.get('Constraints')
ds.replicas_max_per_node = placement.get('MaxReplicas')
placement_preferences = []
for preference in placement.get('Preferences', []):
placement_preferences.append(
Expand Down Expand Up @@ -2603,6 +2626,7 @@ def main():
placement=dict(type='dict', options=dict(
constraints=dict(type='list', elements='str'),
preferences=dict(type='list', elements='dict'),
replicas_max_per_node=dict(type='int'),
)),
tty=dict(type='bool'),
dns=dict(type='list', elements='str'),
Expand Down Expand Up @@ -2748,6 +2772,14 @@ def main():
) is not None,
usage_msg='set placement.constraints'
),
placement_config_replicas_max_per_node=dict(
docker_py_version='4.4.3',
docker_api_version='1.40',
detect_usage=lambda c: (c.module.params['placement'] or {}).get(
'replicas_max_per_node'
) is not None,
usage_msg='set placement.replicas_max_per_node'
),
mounts_tmpfs=dict(
docker_py_version='2.6.0',
detect_usage=_detect_mount_tmpfs_usage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,59 @@
- constraints_1 is failed
- "'Minimum version required' in constraints_1.msg"
when: docker_api_version is version('1.27', '<') or docker_py_version is version('2.4.0', '<')

####################################################################
## placement.replicas_max_per_node #####################################################
####################################################################

- name: placement.replicas_max_per_node
docker_swarm_service:
name: "{{ service_name }}"
image: "{{ docker_test_image_alpine }}"
resolve_image: no
command: '/bin/sh -v -c "sleep 10m"'
placement:
replicas_max_per_node: 1
register: replicas_max_per_node_1
ignore_errors: yes

- name: placement.replicas_max_per_node (idempotency)
docker_swarm_service:
name: "{{ service_name }}"
image: "{{ docker_test_image_alpine }}"
resolve_image: no
command: '/bin/sh -v -c "sleep 10m"'
placement:
replicas_max_per_node: 1
register: replicas_max_per_node_2
ignore_errors: yes

- name: placement.replicas_max_per_node (change)
docker_swarm_service:
name: "{{ service_name }}"
image: "{{ docker_test_image_alpine }}"
resolve_image: no
command: '/bin/sh -v -c "sleep 10m"'
placement:
replicas_max_per_node: 2
register: replicas_max_per_node_3
ignore_errors: yes


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

- assert:
that:
- replicas_max_per_node_1 is changed
- replicas_max_per_node_2 is not changed
- replicas_max_per_node_3 is changed
when: docker_api_version is version('1.40', '>=') and docker_py_version is version('4.4.3', '>=')
- assert:
that:
- replicas_max_per_node_1 is failed
- "'Minimum version required' in replicas_max_per_node_1.msg"
when: docker_api_version is version('1.40', '<') or docker_py_version is version('4.4.3', '<')
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ service_expected_output:
- {mode: null, protocol: udp, published_port: 60001, target_port: 60001}
read_only: null
replicas: null
replicas_max_per_node: null
reserve_cpu: null
reserve_memory: null
restart_policy: null
Expand Down

0 comments on commit 3ddd75a

Please sign in to comment.