summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fontein <felix@fontein.de>2020-02-03 23:27:40 +0100
committerGitHub <noreply@github.com>2020-02-03 23:27:40 +0100
commit23b2bb4f4dc68ffa385e74b5d5c304f461887965 (patch)
treef2428c771381500f07d3c3cb76cc53fa35550220
parent21ae66db2ecea3fef21b9b73b5e890809d58631e (diff)
downloadansible-23b2bb4f4dc68ffa385e74b5d5c304f461887965.tar.gz
docker_container: change behavior for one-port container ranges to be same as docker CLI (#66382)
* Adjust docker_container behavior for one-port container ranges to be similar to docker CLI. * Add changelog. * Add documented examples for ports:.
-rw-r--r--changelogs/fragments/66382-docker_container-port-range.yml3
-rw-r--r--docs/docsite/rst/porting_guides/porting_guide_2.10.rst1
-rw-r--r--lib/ansible/modules/cloud/docker/docker_container.py21
-rw-r--r--test/integration/targets/docker_container/tasks/tests/ports.yml66
4 files changed, 89 insertions, 2 deletions
diff --git a/changelogs/fragments/66382-docker_container-port-range.yml b/changelogs/fragments/66382-docker_container-port-range.yml
new file mode 100644
index 0000000000..7e504aee5f
--- /dev/null
+++ b/changelogs/fragments/66382-docker_container-port-range.yml
@@ -0,0 +1,3 @@
+minor_changes:
+ - "docker_container - support for port ranges was adjusted to be more compatible to the ``docker`` command line utility:
+ a one-port container range combined with a multiple-port host range will no longer result in only the first host port be used, but the whole range being passed to Docker so that a free port in that range will be used."
diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.10.rst b/docs/docsite/rst/porting_guides/porting_guide_2.10.rst
index 74a8aed46b..331b97f52e 100644
--- a/docs/docsite/rst/porting_guides/porting_guide_2.10.rst
+++ b/docs/docsite/rst/porting_guides/porting_guide_2.10.rst
@@ -109,6 +109,7 @@ Noteworthy module changes
* Junction points are no longer reported as ``islnk``, use ``isjunction`` to properly report these files. This behaviour matches the :ref:`win_stat <win_stat_module>`
* Directories no longer return a ``size``, this matches the ``stat`` and ``find`` behaviour and has been removed due to the difficulties in correctly reporting the size of a directory
* :ref:`docker_container <docker_container_module>` no longer passes information on non-anonymous volumes or binds as ``Volumes`` to the Docker daemon. This increases compatibility with the ``docker`` CLI program. Note that if you specify ``volumes: strict`` in ``comparisons``, this could cause existing containers created with docker_container from Ansible 2.9 or earlier to restart.
+* :ref:`docker_container <docker_container_module>`'s support for port ranges was adjusted to be more compatible to the ``docker`` command line utility: a one-port container range combined with a multiple-port host range will no longer result in only the first host port be used, but the whole range being passed to Docker so that a free port in that range will be used.
* :ref:`purefb_fs <purefb_fs_module>` no longer supports the deprecated ``nfs`` option. This has been superceeded by ``nfsv3``.
Plugins
diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py
index 2c8c7df85d..53eb5131a1 100644
--- a/lib/ansible/modules/cloud/docker/docker_container.py
+++ b/lib/ansible/modules/cloud/docker/docker_container.py
@@ -644,6 +644,9 @@ options:
container port, 9000 is a host port, and 0.0.0.0 is a host interface."
- Port ranges can be used for source and destination ports. If two ranges with
different lengths are specified, the shorter range will be used.
+ Since Ansible 2.10, if the source port range has length 1, the port will not be assigned
+ to the first port of the destination range, but to a free port in that range. This is the
+ same behavior as for C(docker) command line utility.
- "Bind addresses must be either IPv4 or IPv6 addresses. Hostnames are *not* allowed. This
is different from the C(docker) command line utility. Use the L(dig lookup,../lookup/dig.html)
to resolve hostnames."
@@ -886,8 +889,16 @@ EXAMPLES = '''
devices:
- "/dev/sda:/dev/xvda:rwm"
ports:
+ # Publish container port 9000 as host port 8080
- "8080:9000"
+ # Publish container UDP port 9001 as host port 8081 on interface 127.0.0.1
- "127.0.0.1:8081:9001/udp"
+ # Publish container port 9002 as a random host port
+ - "9002"
+ # Publish container port 9003 as a random host port in range 8000-8100
+ - "9003:8000-8100"
+ # Publish container ports 9010-9020 to host ports 7000-7010
+ - "9010-9020:7000-7010"
env:
SECRET_KEY: "ssssh"
# Values which might be parsed as numbers, booleans or other types by the YAML parser need to be quoted
@@ -1656,7 +1667,10 @@ class TaskParameters(DockerBaseClass):
if p_len == 1:
port_binds = len(container_ports) * [(default_ip,)]
elif p_len == 2:
- port_binds = [(default_ip, port) for port in parse_port_range(parts[0], self.client)]
+ if len(container_ports) == 1:
+ port_binds = [(default_ip, parts[0])]
+ else:
+ 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
ipaddr = parts[0]
@@ -1666,7 +1680,10 @@ class TaskParameters(DockerBaseClass):
if re.match(r'^\[[0-9a-fA-F:]+\]$', ipaddr):
ipaddr = ipaddr[1:-1]
if parts[1]:
- port_binds = [(ipaddr, port) for port in parse_port_range(parts[1], self.client)]
+ if len(container_ports) == 1:
+ port_binds = [(ipaddr, parts[1])]
+ else:
+ port_binds = [(ipaddr, port) for port in parse_port_range(parts[1], self.client)]
else:
port_binds = len(container_ports) * [(ipaddr,)]
diff --git a/test/integration/targets/docker_container/tasks/tests/ports.yml b/test/integration/targets/docker_container/tasks/tests/ports.yml
index 71014e11c3..e60fb3245a 100644
--- a/test/integration/targets/docker_container/tasks/tests/ports.yml
+++ b/test/integration/targets/docker_container/tasks/tests/ports.yml
@@ -2,6 +2,10 @@
- name: Registering container name
set_fact:
cname: "{{ cname_prefix ~ '-options' }}"
+ cname2: "{{ cname_prefix ~ '-options-h1' }}"
+- name: Registering container name
+ set_fact:
+ cnames: "{{ cnames + [cname, cname2] }}"
####################################################################
## published_ports: all ############################################
@@ -157,6 +161,68 @@
- published_ports_3 is changed
####################################################################
+## published_ports: one-element container port range ###############
+####################################################################
+
+- name: published_ports -- one-element container port range
+ docker_container:
+ image: alpine:3.8
+ command: '/bin/sh -c "sleep 10m"'
+ name: "{{ item }}"
+ state: started
+ published_ports:
+ - "9010-9050:9010"
+ force_kill: yes
+ loop:
+ - '{{ cname }}'
+ - '{{ cname2 }}'
+ register: published_ports_1
+
+- name: published_ports -- one-element container port range (idempotency)
+ docker_container:
+ image: alpine:3.8
+ command: '/bin/sh -c "sleep 10m"'
+ name: "{{ item }}"
+ state: started
+ published_ports:
+ - "9010-9050:9010"
+ force_kill: yes
+ loop:
+ - '{{ cname }}'
+ - '{{ cname2 }}'
+ register: published_ports_2
+
+- name: published_ports -- one-element container port range (different range)
+ docker_container:
+ image: alpine:3.8
+ command: '/bin/sh -c "sleep 10m"'
+ name: "{{ item }}"
+ state: started
+ published_ports:
+ - "9010-9051:9010"
+ force_kill: yes
+ loop:
+ - '{{ cname }}'
+ - '{{ cname2 }}'
+ register: published_ports_3
+
+- name: cleanup
+ docker_container:
+ name: "{{ item }}"
+ state: absent
+ force_kill: yes
+ loop:
+ - '{{ cname }}'
+ - '{{ cname2 }}'
+ diff: no
+
+- assert:
+ that:
+ - published_ports_1 is changed
+ - published_ports_2 is not changed
+ - published_ports_3 is changed
+
+####################################################################
## published_ports: IPv6 addresses #################################
####################################################################