diff --git a/changelogs/fragments/47997-docker_container-ipc-pid-mode.yml b/changelogs/fragments/47997-docker_container-ipc-pid-mode.yml new file mode 100644 index 00000000000..37dcdfed9a1 --- /dev/null +++ b/changelogs/fragments/47997-docker_container-ipc-pid-mode.yml @@ -0,0 +1,2 @@ +bugfixes: +- "docker_container - fix ``ipc_mode`` and ``pid_mode`` idempotency if the ``host:`` form is used (as opposed to ``host:``)." diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index 65aa9da1047..b2eb71fa6e5 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -330,7 +330,8 @@ options: default: 'no' pid_mode: description: - - Set the PID namespace mode for the container. Currently only supports 'host'. + - Set the PID namespace mode for the container. + - Note that docker-py < 2.0 only supports 'host'. Newer versions allow all values supported by the docker daemon. privileged: description: - Give extended privileges to the container. @@ -1003,6 +1004,8 @@ class TaskParameters(DockerBaseClass): self.healthcheck, self.disable_healthcheck = self._parse_healthcheck() self.exp_links = None self.volume_binds = self._get_volume_binds(self.volumes) + self.pid_mode = self._replace_container_names(self.pid_mode) + self.ipc_mode = self._replace_container_names(self.ipc_mode) self.log("volumes:") self.log(self.volumes, pretty_print=True) @@ -1555,6 +1558,24 @@ class TaskParameters(DockerBaseClass): setattr(self, option, devices_list) + def _replace_container_names(self, mode): + """ + Parse IPC and PID modes. If they contain a container name, replace + with the container's ID. + """ + if mode is None or not mode.startswith('container:'): + return mode + container_name = mode[len('container:'):] + # Try to inspect container to see whether this is an ID or a + # name (and in the latter case, retrieve it's ID) + container = self.client.get_container(container_name) + if container is None: + # If we can't find the container, issue a warning and continue with + # what the user specified. + self.client.module.warn('Cannot find a container with name or ID "{0}"'.format(container_name)) + return mode + return 'container:{0}'.format(container['Id']) + class Container(DockerBaseClass): diff --git a/test/integration/targets/docker_container/tasks/tests/options.yml b/test/integration/targets/docker_container/tasks/tests/options.yml index 84b2e65cb96..6bff35c846f 100644 --- a/test/integration/targets/docker_container/tasks/tests/options.yml +++ b/test/integration/targets/docker_container/tasks/tests/options.yml @@ -1781,8 +1781,8 @@ command: '/bin/sh -c "sleep 10m"' name: "{{ cname }}" state: started - #ipc_mode: "container:{{ cname_h1 }}" - ipc_mode: shareable + ipc_mode: "container:{{ cname_h1 }}" + # ipc_mode: shareable register: ipc_mode_1 - name: ipc_mode (idempotency) @@ -1791,9 +1791,8 @@ command: '/bin/sh -c "sleep 10m"' name: "{{ cname }}" state: started - # THIS IS CURRENTLY NOT IDEMPOTENT! SEE https://github.com/ansible/ansible/issues/45829 - # ipc_mode: "container:{{ cname_h1 }}" - ipc_mode: shareable + ipc_mode: "container:{{ cname_h1 }}" + # ipc_mode: shareable register: ipc_mode_2 - name: ipc_mode (change) @@ -2694,7 +2693,7 @@ command: '/bin/sh -c "sleep 10m"' name: "{{ cname }}" state: started - pid_mode: "container:{{ pid_mode_helper.ansible_facts.docker_container.Id }}" + pid_mode: "container:{{ cname_h1 }}" register: pid_mode_2 ignore_errors: yes # docker-py < 2.0 does not support "arbitrary" pid_mode values