diff --git a/changelogs/fragments/1214-docker_container-ports.yml b/changelogs/fragments/1214-docker_container-ports.yml new file mode 100644 index 00000000..8f5a3467 --- /dev/null +++ b/changelogs/fragments/1214-docker_container-ports.yml @@ -0,0 +1,3 @@ +bugfixes: + - "docker_container - when the same port is mapped more than once for the same protocol without specifying an interface, a bug caused an invalid value to be passed for the interface + (https://github.com/ansible-collections/community.docker/issues/1213, https://github.com/ansible-collections/community.docker/pull/1214)." diff --git a/plugins/module_utils/_module_container/docker_api.py b/plugins/module_utils/_module_container/docker_api.py index fa66d23f..c9bcede8 100644 --- a/plugins/module_utils/_module_container/docker_api.py +++ b/plugins/module_utils/_module_container/docker_api.py @@ -29,6 +29,7 @@ from ansible_collections.community.docker.plugins.module_utils._common_api impor RequestException, ) from ansible_collections.community.docker.plugins.module_utils._module_container.base import ( + _DEFAULT_IP_REPLACEMENT_STRING, OPTION_AUTO_REMOVE, OPTION_BLKIO_WEIGHT, OPTION_CAP_DROP, @@ -127,11 +128,6 @@ if t.TYPE_CHECKING: Sentry = object -_DEFAULT_IP_REPLACEMENT_STRING = ( - "[[DEFAULT_IP:iewahhaeB4Sae6Aen8IeShairoh4zeph7xaekoh8Geingunaesaeweiy3ooleiwi]]" -) - - _SENTRY: Sentry = object() @@ -2093,16 +2089,26 @@ def _preprocess_value_ports( if "published_ports" not in values: return values found = False - for port_spec in values["published_ports"].values(): - if port_spec[0] == _DEFAULT_IP_REPLACEMENT_STRING: - found = True - break + for port_specs in values["published_ports"].values(): + if not isinstance(port_specs, list): + port_specs = [port_specs] + for port_spec in port_specs: + if port_spec[0] == _DEFAULT_IP_REPLACEMENT_STRING: + found = True + break if not found: return values default_ip = _get_default_host_ip(module, client) - for port, port_spec in values["published_ports"].items(): - if port_spec[0] == _DEFAULT_IP_REPLACEMENT_STRING: - values["published_ports"][port] = tuple([default_ip] + list(port_spec[1:])) + for port, port_specs in values["published_ports"].items(): + if isinstance(port_specs, list): + for index, port_spec in enumerate(port_specs): + if port_spec[0] == _DEFAULT_IP_REPLACEMENT_STRING: + port_specs[index] = tuple([default_ip] + list(port_spec[1:])) + else: + if port_specs[0] == _DEFAULT_IP_REPLACEMENT_STRING: + values["published_ports"][port] = tuple( + [default_ip] + list(port_specs[1:]) + ) return values diff --git a/tests/integration/targets/docker_container/tasks/tests/ports.yml b/tests/integration/targets/docker_container/tasks/tests/ports.yml index 95a59a78..4581ca9a 100644 --- a/tests/integration/targets/docker_container/tasks/tests/ports.yml +++ b/tests/integration/targets/docker_container/tasks/tests/ports.yml @@ -277,6 +277,58 @@ - published_ports_2 is not changed - published_ports_3 is changed +#################################################################### +## published_ports: duplicate ports ################################ +#################################################################### + +- name: published_ports -- duplicate ports + community.docker.docker_container: + image: "{{ docker_test_image_alpine }}" + command: '/bin/sh -c "sleep 10m"' + name: "{{ cname }}" + state: started + published_ports: + - 8000:80 + - 10000:80 + register: published_ports_1 + +- name: published_ports -- duplicate ports (idempotency) + community.docker.docker_container: + image: "{{ docker_test_image_alpine }}" + command: '/bin/sh -c "sleep 10m"' + name: "{{ cname }}" + state: started + published_ports: + - 8000:80 + - 10000:80 + force_kill: true + register: published_ports_2 + +- name: published_ports -- duplicate ports (idempotency w/ protocol) + community.docker.docker_container: + image: "{{ docker_test_image_alpine }}" + command: '/bin/sh -c "sleep 10m"' + name: "{{ cname }}" + state: started + published_ports: + - 8000:80/tcp + - 10000:80/tcp + force_kill: true + register: published_ports_3 + +- name: cleanup + community.docker.docker_container: + name: "{{ cname }}" + state: absent + force_kill: true + diff: false + +- ansible.builtin.assert: + that: + - published_ports_1 is changed + - published_ports_2 is not changed + - published_ports_3 is not changed + #################################################################### ## published_ports: IPv6 addresses ################################# ####################################################################