From ae62f4be32aad4afbd402d800950b994f8563563 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 4 Sep 2018 23:20:34 +0200 Subject: [PATCH] [2.6] docker_container: fix check mode for container creation (#44760) * docker_container: fix check mode for container creation (#42380) * Create copy of HostConfig object before adding it to results. * Create general sanitize function in docker_common. Using it for all return values of docker_container. * Make Python 2.6 compatible. * Added changelog. --- .../42380-docker_container-check-mode.yaml | 2 ++ lib/ansible/module_utils/docker_common.py | 18 ++++++++++++++++++ .../modules/cloud/docker/docker_container.py | 6 +++--- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/42380-docker_container-check-mode.yaml diff --git a/changelogs/fragments/42380-docker_container-check-mode.yaml b/changelogs/fragments/42380-docker_container-check-mode.yaml new file mode 100644 index 00000000000..68f3666b6f1 --- /dev/null +++ b/changelogs/fragments/42380-docker_container-check-mode.yaml @@ -0,0 +1,2 @@ +bugfixes: +- "fixes docker_container check and debug mode (https://github.com/ansible/ansible/pull/42380)" diff --git a/lib/ansible/module_utils/docker_common.py b/lib/ansible/module_utils/docker_common.py index 41e61ee84d5..64406c1166a 100644 --- a/lib/ansible/module_utils/docker_common.py +++ b/lib/ansible/module_utils/docker_common.py @@ -120,6 +120,24 @@ if not HAS_DOCKER_PY: pass +def sanitize_result(data): + """Sanitize data object for return to Ansible. + + When the data object contains types such as docker.types.containers.HostConfig, + Ansible will fail when these are returned via exit_json or fail_json. + HostConfig is derived from dict, but its constructor requires additional + arguments. This function sanitizes data structures by recursively converting + everything derived from dict to dict and everything derived from list (and tuple) + to a list. + """ + if isinstance(data, dict): + return dict((k, sanitize_result(v)) for k, v in data.items()) + elif isinstance(data, (list, tuple)): + return [sanitize_result(v) for v in data] + else: + return data + + class DockerBaseClass(object): def __init__(self): diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index c49092c7f30..fe068c9fb52 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -611,7 +611,7 @@ import shlex from distutils.version import LooseVersion from ansible.module_utils.basic import human_to_bytes -from ansible.module_utils.docker_common import HAS_DOCKER_PY_2, HAS_DOCKER_PY_3, AnsibleDockerClient, DockerBaseClass +from ansible.module_utils.docker_common import HAS_DOCKER_PY_2, HAS_DOCKER_PY_3, AnsibleDockerClient, DockerBaseClass, sanitize_result from ansible.module_utils.six import string_types try: @@ -1795,7 +1795,7 @@ class ContainerManager(DockerBaseClass): self.container_remove(container.Id) def fail(self, msg, **kwargs): - self.client.module.fail_json(msg=msg, **kwargs) + self.client.module.fail_json(msg=msg, **sanitize_result(kwargs)) def _get_container(self, container): ''' @@ -2122,7 +2122,7 @@ def main(): ) cm = ContainerManager(client) - client.module.exit_json(**cm.results) + client.module.exit_json(**sanitize_result(cm.results)) if __name__ == '__main__':