From 23ba177f9ec6092bb07c05bf374ef9a75e2f6903 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 14 Jul 2022 09:56:50 +0200 Subject: [PATCH] Implement platform parameter for docker_container, first version. --- .../426-docker_container-platform.yml | 2 + plugins/module_utils/module_container/base.py | 8 ++- .../module_container/docker_api.py | 24 ++++++- .../module_utils/module_container/module.py | 3 +- plugins/modules/docker_container.py | 8 +++ .../docker_container/tasks/tests/options.yml | 66 +++++++++++++++++++ 6 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/426-docker_container-platform.yml diff --git a/changelogs/fragments/426-docker_container-platform.yml b/changelogs/fragments/426-docker_container-platform.yml new file mode 100644 index 000000000..9b79a050b --- /dev/null +++ b/changelogs/fragments/426-docker_container-platform.yml @@ -0,0 +1,2 @@ +minor_changes: + - "docker_container - allow to specify ``platform`` (https://github.com/ansible-collections/community.docker/issues/123, https://github.com/ansible-collections/community.docker/pull/426)." diff --git a/plugins/module_utils/module_container/base.py b/plugins/module_utils/module_container/base.py index 97b84bf04..f662a5172 100644 --- a/plugins/module_utils/module_container/base.py +++ b/plugins/module_utils/module_container/base.py @@ -246,7 +246,7 @@ def inspect_image_by_name(self, client, repository, tag): pass @abc.abstractmethod - def pull_image(self, client, repository, tag): + def pull_image(self, client, repository, tag, platform=None): pass @abc.abstractmethod @@ -995,6 +995,11 @@ def _preprocess_ports(module, values): .add_option('pids_limit', type='int') ) +OPTION_PLATFORM = ( + OptionGroup() + .add_option('platform', type='str') +) + OPTION_PRIVILEGED = ( OptionGroup() .add_option('privileged', type='bool') @@ -1162,6 +1167,7 @@ def _preprocess_ports(module, values): OPTION_OOM_SCORE_ADJ, OPTION_PID_MODE, OPTION_PIDS_LIMIT, + OPTION_PLATFORM, OPTION_PRIVILEGED, OPTION_READ_ONLY, OPTION_RESTART_POLICY, diff --git a/plugins/module_utils/module_container/docker_api.py b/plugins/module_utils/module_container/docker_api.py index c4f213b12..602ec708c 100644 --- a/plugins/module_utils/module_container/docker_api.py +++ b/plugins/module_utils/module_container/docker_api.py @@ -64,6 +64,7 @@ OPTION_OOM_SCORE_ADJ, OPTION_PID_MODE, OPTION_PIDS_LIMIT, + OPTION_PLATFORM, OPTION_PRIVILEGED, OPTION_READ_ONLY, OPTION_RESTART_POLICY, @@ -216,8 +217,8 @@ def inspect_image_by_id(self, client, image_id): def inspect_image_by_name(self, client, repository, tag): return client.find_image(repository, tag) - def pull_image(self, client, repository, tag): - return client.pull_image(repository, tag) + def pull_image(self, client, repository, tag, platform=None): + return client.pull_image(repository, tag, platform=platform) def pause_container(self, client, container_id): client.post_call('/containers/{0}/pause', container_id) @@ -254,6 +255,8 @@ def connect_container_to_network(self, client, container_id, network_id, paramet def create_container(self, client, container_name, create_parameters): params = {'name': container_name} + if 'platform' in create_parameters: + params['platform'] = create_parameters.pop('platform') new_container = client.post_json_to_json('/containers/create', data=create_parameters, params=params) client.report_warnings(new_container) return new_container['Id'] @@ -1030,6 +1033,17 @@ def _set_values_log(module, data, api_version, options, values): data['HostConfig']['LogConfig'] = log_config +def _get_values_platform(module, container, api_version, options): + return { + 'platform': container.get('Platform'), + } + + +def _set_values_platform(module, data, api_version, options, values): + if 'platform' in values: + data['platform'] = values['platform'] + + def _get_values_restart(module, container, api_version, options): restart_policy = container['HostConfig'].get('RestartPolicy') or {} return { @@ -1273,6 +1287,12 @@ def _preprocess_container_names(module, client, api_version, value): OPTION_PIDS_LIMIT.add_engine('docker_api', DockerAPIEngine.host_config_value('PidsLimit')) +OPTION_PLATFORM.add_engine('docker_api', DockerAPIEngine( + get_value=_get_values_platform, + set_value=_set_values_platform, + min_api_version='1.41', +)) + OPTION_PRIVILEGED.add_engine('docker_api', DockerAPIEngine.host_config_value('Privileged')) OPTION_READ_ONLY.add_engine('docker_api', DockerAPIEngine.host_config_value('ReadonlyRootfs')) diff --git a/plugins/module_utils/module_container/module.py b/plugins/module_utils/module_container/module.py index 56d266b2d..9abb1c8a9 100644 --- a/plugins/module_utils/module_container/module.py +++ b/plugins/module_utils/module_container/module.py @@ -392,7 +392,8 @@ def _get_image(self): if not image or self.param_pull: if not self.check_mode: self.log("Pull the image.") - image, alreadyToLatest = self.engine_driver.pull_image(self.client, repository, tag) + image, alreadyToLatest = self.engine_driver.pull_image( + self.client, repository, tag, platform=self.module.params['platform']) if alreadyToLatest: self.results['changed'] = False else: diff --git a/plugins/modules/docker_container.py b/plugins/modules/docker_container.py index 42f2d5b3d..e7fa787c8 100644 --- a/plugins/modules/docker_container.py +++ b/plugins/modules/docker_container.py @@ -676,6 +676,14 @@ - Set PIDs limit for the container. It accepts an integer value. - Set C(-1) for unlimited PIDs. type: int + platform: + description: + - Platform for the container in the format C(os[/arch[/variant]]). + - "Please note that inspecting the container does not always return the exact platform string used to + create the container. This can cause idempotency to break for this module. Use the I(comparisons) option + with C(platform: ignore) to prevent accidental recreation of the container due to this." + type: str + version_added: 3.0.0 privileged: description: - Give extended privileges to the container. diff --git a/tests/integration/targets/docker_container/tasks/tests/options.yml b/tests/integration/targets/docker_container/tasks/tests/options.yml index 4a0ccf775..60d358bd3 100644 --- a/tests/integration/targets/docker_container/tasks/tests/options.yml +++ b/tests/integration/targets/docker_container/tasks/tests/options.yml @@ -3178,6 +3178,72 @@ avoid such warnings, please quote the value.' in (log_options_2.warnings | defau - pids_limit_2 is not changed - pids_limit_3 is changed +#################################################################### +## platform ######################################################## +#################################################################### + +- name: Remove hello-world image + docker_image: + name: hello-world:latest + state: absent + +- name: platform + docker_container: + image: hello-world:latest + name: "{{ cname }}" + state: present + pull: true + platform: linux/amd64 + debug: true + register: platform_1 + ignore_errors: yes + +- name: platform (idempotency) + docker_container: + image: hello-world:latest + name: "{{ cname }}" + state: present + # The container always reports 'linux' as platform instead of 'linux/amd64'... + platform: linux + debug: true + register: platform_2 + ignore_errors: yes + +- name: platform (changed) + docker_container: + image: hello-world:latest + name: "{{ cname }}" + state: present + pull: true + platform: linux/386 + force_kill: yes + debug: true + comparisons: + # Do not restart because of the changed image ID + image: ignore + register: platform_3 + ignore_errors: yes + +- name: cleanup + docker_container: + name: "{{ cname }}" + state: absent + force_kill: yes + diff: no + +- assert: + that: + - platform_1 is changed + - platform_2 is not changed and platform_2 is not failed + - platform_3 is changed + when: docker_api_version is version('1.41', '>=') +- assert: + that: + - platform_1 is failed + - | + ('API version is ' ~ docker_api_version ~ '.') in platform_1.msg and 'Minimum version required is 1.41 ' in platform_1.msg + when: docker_api_version is version('1.41', '<') + #################################################################### ## privileged ###################################################### ####################################################################