From e26890a90929c690c590d2aefdbfffb8cefdd97b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 15 Jul 2022 17:14:57 +0200 Subject: [PATCH] Implement platform parameter for docker_container, first version. (#426) --- .../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 00000000..9b79a050 --- /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 7fd21da0..70f0afe0 100644 --- a/plugins/module_utils/module_container/base.py +++ b/plugins/module_utils/module_container/base.py @@ -246,7 +246,7 @@ class EngineDriver(object): pass @abc.abstractmethod - def pull_image(self, client, repository, tag): + def pull_image(self, client, repository, tag, platform=None): pass @abc.abstractmethod @@ -1000,6 +1000,11 @@ OPTION_PIDS_LIMIT = ( .add_option('pids_limit', type='int') ) +OPTION_PLATFORM = ( + OptionGroup() + .add_option('platform', type='str') +) + OPTION_PRIVILEGED = ( OptionGroup() .add_option('privileged', type='bool') @@ -1168,6 +1173,7 @@ OPTIONS = [ 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 74e074f7..fe20dbc1 100644 --- a/plugins/module_utils/module_container/docker_api.py +++ b/plugins/module_utils/module_container/docker_api.py @@ -65,6 +65,7 @@ from ansible_collections.community.docker.plugins.module_utils.module_container. OPTION_OOM_SCORE_ADJ, OPTION_PID_MODE, OPTION_PIDS_LIMIT, + OPTION_PLATFORM, OPTION_PRIVILEGED, OPTION_READ_ONLY, OPTION_RESTART_POLICY, @@ -217,8 +218,8 @@ class DockerAPIEngineDriver(EngineDriver): 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) @@ -255,6 +256,8 @@ class DockerAPIEngineDriver(EngineDriver): 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'] @@ -1031,6 +1034,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 { @@ -1276,6 +1290,12 @@ OPTION_PID_MODE.add_engine('docker_api', DockerAPIEngine.host_config_value('PidM 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 b4e9ab37..e354347a 100644 --- a/plugins/module_utils/module_container/module.py +++ b/plugins/module_utils/module_container/module.py @@ -407,7 +407,8 @@ class ContainerManager(DockerBaseClass): 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 17cd8aed..4946c3cd 100644 --- a/plugins/modules/docker_container.py +++ b/plugins/modules/docker_container.py @@ -698,6 +698,14 @@ options: - 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 02d7787d..57056b8f 100644 --- a/tests/integration/targets/docker_container/tasks/tests/options.yml +++ b/tests/integration/targets/docker_container/tasks/tests/options.yml @@ -3253,6 +3253,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 ###################################################### ####################################################################