1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

docker_swarm_service: Don’t remove service when networks change (#52634)

* Don’t remove service when networks change

* Add changelog fragment

* Some more network integration tests

* Add hannseman as author

* Remove return on self.client.fail
This commit is contained in:
Hannes Ljungberg 2019-02-21 12:46:50 +01:00 committed by John R Barker
parent 19cf956453
commit 7276344f85
3 changed files with 86 additions and 10 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- "docker_swarm_service - Don't recreate service when ``networks`` parameter changes when running Docker API >= 1.29."

View file

@ -12,7 +12,10 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: docker_swarm_service module: docker_swarm_service
author: "Dario Zanzico (@dariko), Jason Witkowski (@jwitko)" author:
- "Dario Zanzico (@dariko)"
- "Jason Witkowski (@jwitko)"
- "Hannes Ljungberg (@hannseman)"
short_description: docker swarm service short_description: docker swarm service
description: description:
- Manages docker services via a swarm manager node. - Manages docker services via a swarm manager node.
@ -331,6 +334,8 @@ options:
networks: networks:
description: description:
- List of the service networks names. - List of the service networks names.
- Prior to API version 1.29, updating and removing networks is not supported.
If changes are made the service will then be removed and recreated.
- Corresponds to the C(--network) option of C(docker service create). - Corresponds to the C(--network) option of C(docker service create).
type: list type: list
stop_signal: stop_signal:
@ -367,6 +372,7 @@ options:
mode: mode:
description: description:
- What publish mode to use. - What publish mode to use.
- Service will be removed and recreated when changed.
- Requires API version >= 1.32. - Requires API version >= 1.32.
type: str type: str
choices: choices:
@ -757,6 +763,7 @@ class DockerService(DockerBaseClass):
self.update_max_failure_ratio = None self.update_max_failure_ratio = None
self.update_order = None self.update_order = None
self.working_dir = None self.working_dir = None
self.can_update_networks = None
def get_facts(self): def get_facts(self):
return { return {
@ -805,9 +812,10 @@ class DockerService(DockerBaseClass):
} }
@staticmethod @staticmethod
def from_ansible_params(ap, old_service, image_digest): def from_ansible_params(ap, old_service, image_digest, can_update_networks):
s = DockerService() s = DockerService()
s.image = image_digest s.image = image_digest
s.can_update_networks = can_update_networks
s.constraints = ap['constraints'] s.constraints = ap['constraints']
s.placement_preferences = ap['placement_preferences'] s.placement_preferences = ap['placement_preferences']
s.args = ap['args'] s.args = ap['args']
@ -962,7 +970,7 @@ class DockerService(DockerBaseClass):
differences.add('secrets', parameter=self.secrets, active=os.secrets) differences.add('secrets', parameter=self.secrets, active=os.secrets)
if self.networks is not None and self.networks != (os.networks or []): if self.networks is not None and self.networks != (os.networks or []):
differences.add('networks', parameter=self.networks, active=os.networks) differences.add('networks', parameter=self.networks, active=os.networks)
needs_rebuild = True needs_rebuild = not self.can_update_networks
if self.replicas != os.replicas: if self.replicas != os.replicas:
differences.add('replicas', parameter=self.replicas, active=os.replicas) differences.add('replicas', parameter=self.replicas, active=os.replicas)
if self.command is not None and self.command != (os.command or []): if self.command is not None and self.command != (os.command or []):
@ -1520,6 +1528,10 @@ class DockerServiceManager(object):
digest = distribution_data['Descriptor']['digest'] digest = distribution_data['Descriptor']['digest']
return '%s@%s' % (name, digest) return '%s@%s' % (name, digest)
def can_update_networks(self):
# Before Docker API 1.29 adding/removing networks was not supported
return self.client.docker_api_version >= LooseVersion('1.29')
def run(self): def run(self):
self.diff_tracker = DifferenceTracker() self.diff_tracker = DifferenceTracker()
module = self.client.module module = self.client.module
@ -1532,21 +1544,29 @@ class DockerServiceManager(object):
) )
except DockerException as e: except DockerException as e:
self.client.fail( self.client.fail(
"Error looking for an image named %s: %s" % (image, e)) 'Error looking for an image named %s: %s'
% (image, e)
)
try: try:
current_service = self.get_service(module.params['name']) current_service = self.get_service(module.params['name'])
except Exception as e: except Exception as e:
self.client.fail( self.client.fail(
"Error looking for service named %s: %s" % (module.params['name'], e)) 'Error looking for service named %s: %s'
% (module.params['name'], e)
)
try: try:
can_update_networks = self.can_update_networks()
new_service = DockerService.from_ansible_params( new_service = DockerService.from_ansible_params(
module.params, module.params,
current_service, current_service,
image_digest image_digest,
can_update_networks
) )
except Exception as e: except Exception as e:
self.client.fail( return self.client.fail(
"Error parsing module parameters: %s" % e) 'Error parsing module parameters: %s' % e
)
changed = False changed = False
msg = 'noop' msg = 'noop'

View file

@ -1551,13 +1551,51 @@
- "{{ network_name_1 }}" - "{{ network_name_1 }}"
register: networks_2 register: networks_2
- name: networks (change more)
docker_swarm_service:
name: "{{ service_name }}"
image: alpine:3.8
command: '/bin/sh -v -c "sleep 10m"'
networks:
- "{{ network_name_1 }}"
- "{{ network_name_2 }}"
register: networks_3
- name: networks (change more idempotency)
docker_swarm_service:
name: "{{ service_name }}"
image: alpine:3.8
command: '/bin/sh -v -c "sleep 10m"'
networks:
- "{{ network_name_1 }}"
- "{{ network_name_2 }}"
register: networks_4
- name: networks (change less)
docker_swarm_service:
name: "{{ service_name }}"
image: alpine:3.8
command: '/bin/sh -v -c "sleep 10m"'
networks:
- "{{ network_name_2 }}"
register: networks_5
- name: networks (change less idempotency)
docker_swarm_service:
name: "{{ service_name }}"
image: alpine:3.8
command: '/bin/sh -v -c "sleep 10m"'
networks:
- "{{ network_name_2 }}"
register: networks_6
- name: networks (empty) - name: networks (empty)
docker_swarm_service: docker_swarm_service:
name: "{{ service_name }}" name: "{{ service_name }}"
image: alpine:3.8 image: alpine:3.8
command: '/bin/sh -v -c "sleep 10m"' command: '/bin/sh -v -c "sleep 10m"'
networks: [] networks: []
register: networks_3 register: networks_7
- name: networks (empty idempotency) - name: networks (empty idempotency)
docker_swarm_service: docker_swarm_service:
@ -1565,7 +1603,7 @@
image: alpine:3.8 image: alpine:3.8
command: '/bin/sh -v -c "sleep 10m"' command: '/bin/sh -v -c "sleep 10m"'
networks: [] networks: []
register: networks_4 register: networks_8
- name: cleanup - name: cleanup
docker_swarm_service: docker_swarm_service:
@ -1579,6 +1617,22 @@
- networks_2 is not changed - networks_2 is not changed
- networks_3 is changed - networks_3 is changed
- networks_4 is not changed - networks_4 is not changed
- networks_5 is changed
- networks_6 is not changed
- networks_7 is changed
- networks_8 is not changed
- assert:
that:
- networks_3.rebuilt == false
- networks_5.rebuilt == false
when: docker_api_version is version('1.29', '>=')
- assert:
that:
- networks_3.rebuilt == true
- networks_5.rebuilt == true
when: docker_api_version is version('1.29', '<')
#################################################################### ####################################################################
## stop_signal ##################################################### ## stop_signal #####################################################