diff --git a/changelogs/fragments/136-docker_swarm_service-fix-idempotence-bug.yml b/changelogs/fragments/136-docker_swarm_service-fix-idempotence-bug.yml new file mode 100644 index 00000000..2155f222 --- /dev/null +++ b/changelogs/fragments/136-docker_swarm_service-fix-idempotence-bug.yml @@ -0,0 +1,2 @@ +bugfixes: +- "docker_swarm_services - avoid crash during idempotence check if ``published_port`` is not specified (https://github.com/ansible-collections/community.docker/issues/107, https://github.com/ansible-collections/community.docker/pull/136)." diff --git a/plugins/modules/docker_swarm_service.py b/plugins/modules/docker_swarm_service.py index d640bf37..2a832312 100644 --- a/plugins/modules/docker_swarm_service.py +++ b/plugins/modules/docker_swarm_service.py @@ -917,7 +917,6 @@ EXAMPLES = ''' import shlex import time -import operator import traceback from distutils.version import LooseVersion @@ -1792,7 +1791,10 @@ class DockerService(DockerBaseClass): old_publish = old_publish or [] if len(self.publish) != len(old_publish): return True - publish_sorter = operator.itemgetter('published_port', 'target_port', 'protocol') + + def publish_sorter(item): + return (item.get('published_port') or 0, item.get('target_port') or 0, item.get('protocol') or '') + publish = sorted(self.publish, key=publish_sorter) old_publish = sorted(old_publish, key=publish_sorter) for publish_item, old_publish_item in zip(publish, old_publish): diff --git a/tests/integration/targets/docker_swarm_service/tasks/tests/options.yml b/tests/integration/targets/docker_swarm_service/tasks/tests/options.yml index df0a5938..ac57a68e 100644 --- a/tests/integration/targets/docker_swarm_service/tasks/tests/options.yml +++ b/tests/integration/targets/docker_swarm_service/tasks/tests/options.yml @@ -1526,6 +1526,40 @@ name: "{{ service_name }}" register: publish_8_info +- name: publish (without published_port) + docker_swarm_service: + name: "{{ service_name }}" + image: "{{ docker_test_image_alpine }}" + resolve_image: no + command: '/bin/sh -v -c "sleep 10m"' + publish: + - protocol: udp + target_port: 60001 + mode: host + register: publish_9 + ignore_errors: yes +- name: gather service info + docker_swarm_service_info: + name: "{{ service_name }}" + register: publish_9_info + +- name: publish (without published_port, idempotence) + docker_swarm_service: + name: "{{ service_name }}" + image: "{{ docker_test_image_alpine }}" + resolve_image: no + command: '/bin/sh -v -c "sleep 10m"' + publish: + - protocol: udp + target_port: 60001 + mode: host + register: publish_10 + ignore_errors: yes +- name: gather service info + docker_swarm_service_info: + name: "{{ service_name }}" + register: publish_10_info + - name: cleanup docker_swarm_service: name: "{{ service_name }}" @@ -1543,6 +1577,8 @@ - publish_7 is not changed - publish_8 is changed - (publish_8_info.service.Endpoint.Ports | length) == 2 + - publish_9 is changed + - publish_10 is not changed when: docker_api_version is version('1.25', '>=') and docker_py_version is version('3.0.0', '>=') - assert: that: