From a7573102bcbc7e88b8bf6de639be2696f1a5ad43 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 2 Aug 2019 17:10:39 +0200 Subject: [PATCH] docker_container: fix port bindings with IPv6 addresses (#59715) * Pass IPv6 addresses for port bindings without square brackets. * Add changelog. * Add test. --- .../59715-docker_container-ipv6-port-bind.yml | 2 ++ .../modules/cloud/docker/docker_container.py | 11 +++++++---- .../docker_container/tasks/tests/options.yml | 13 +++++++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/59715-docker_container-ipv6-port-bind.yml diff --git a/changelogs/fragments/59715-docker_container-ipv6-port-bind.yml b/changelogs/fragments/59715-docker_container-ipv6-port-bind.yml new file mode 100644 index 00000000000..3b4ec86a290 --- /dev/null +++ b/changelogs/fragments/59715-docker_container-ipv6-port-bind.yml @@ -0,0 +1,2 @@ +bugfixes: +- "docker_container - fix port bindings with IPv6 addresses." diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index d31c98a4660..c5ded7c0188 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -1453,13 +1453,16 @@ class TaskParameters(DockerBaseClass): port_binds = [(default_ip, port) for port in parse_port_range(parts[0], self.client)] elif p_len == 3: # We only allow IPv4 and IPv6 addresses for the bind address - if not re.match(r'^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$', parts[0]) and not re.match(r'^\[[0-9a-fA-F:]+\]$', parts[0]): + ipaddr = parts[0] + if not re.match(r'^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$', parts[0]) and not re.match(r'^\[[0-9a-fA-F:]+\]$', ipaddr): self.fail(('Bind addresses for published ports must be IPv4 or IPv6 addresses, not hostnames. ' - 'Use the dig lookup to resolve hostnames. (Found hostname: {0})').format(parts[0])) + 'Use the dig lookup to resolve hostnames. (Found hostname: {0})').format(ipaddr)) + if re.match(r'^\[[0-9a-fA-F:]+\]$', ipaddr): + ipaddr = ipaddr[1:-1] if parts[1]: - port_binds = [(parts[0], port) for port in parse_port_range(parts[1], self.client)] + port_binds = [(ipaddr, port) for port in parse_port_range(parts[1], self.client)] else: - port_binds = len(container_ports) * [(parts[0],)] + port_binds = len(container_ports) * [(ipaddr,)] for bind, container_port in zip(port_binds, container_ports): idx = '{0}/{1}'.format(container_port, protocol) if protocol else container_port diff --git a/test/integration/targets/docker_container/tasks/tests/options.yml b/test/integration/targets/docker_container/tasks/tests/options.yml index 4cf0d2bde29..e594f46cf95 100644 --- a/test/integration/targets/docker_container/tasks/tests/options.yml +++ b/test/integration/targets/docker_container/tasks/tests/options.yml @@ -2804,6 +2804,18 @@ avoid such warnings, please quote the value.' in log_options_2.warnings" force_kill: yes register: published_ports_4 +- name: published_ports (ports with IP addresses) + docker_container: + image: alpine:3.8 + command: '/bin/sh -c "sleep 10m"' + name: "{{ cname }}" + state: started + published_ports: + - '127.0.0.1:9002:9002/tcp' + - '[::1]:9003:9003/tcp' + force_kill: yes + register: published_ports_5 + - name: cleanup docker_container: name: "{{ cname }}" @@ -2817,6 +2829,7 @@ avoid such warnings, please quote the value.' in log_options_2.warnings" - published_ports_2 is not changed - published_ports_3 is not changed - published_ports_4 is changed + - published_ports_5 is changed #################################################################### ## pull ############################################################