From fabba43da7cd25fc14afb6775e16c4687885b9ee Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 28 Aug 2018 13:03:33 +0200 Subject: [PATCH] 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. --- lib/ansible/module_utils/docker_common.py | 18 ++++++++++++++++++ .../modules/cloud/docker/docker_container.py | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/ansible/module_utils/docker_common.py b/lib/ansible/module_utils/docker_common.py index 8cd691db71..454c9fee3b 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 8b1d98fe32..69e2006f71 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -634,7 +634,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: @@ -1817,7 +1817,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 _output_logs(self, msg): self.client.module.log(msg=msg) @@ -2149,7 +2149,7 @@ def main(): ) cm = ContainerManager(client) - client.module.exit_json(**cm.results) + client.module.exit_json(**sanitize_result(cm.results)) if __name__ == '__main__':