From 4985d484155b2a0d6f90f21da99e6f152aad3d02 Mon Sep 17 00:00:00 2001 From: Sergey <6213510+sshnaidm@users.noreply.github.com> Date: Wed, 29 May 2024 18:27:07 +0300 Subject: [PATCH] Reapply "Fix transports issues in podman_image (#619)" (#754) (#755) This reverts commit 391e4c54efb13423c815172398ef87b42a3ae60c. Signed-off-by: Sagi Shnaidman --- plugins/modules/podman_image.py | 73 ++- .../targets/podman_image/tasks/idem_push.yml | 488 ++++++++++++++++++ .../targets/podman_image/tasks/main.yml | 28 +- 3 files changed, 548 insertions(+), 41 deletions(-) create mode 100644 tests/integration/targets/podman_image/tasks/idem_push.yml diff --git a/plugins/modules/podman_image.py b/plugins/modules/podman_image.py index a79566d1..d121cd8f 100644 --- a/plugins/modules/podman_image.py +++ b/plugins/modules/podman_image.py @@ -176,6 +176,7 @@ type: str choices: - dir + - docker - docker-archive - docker-daemon - oci-archive @@ -557,16 +558,8 @@ def present(self): self.results['changed'] = True if self.push: - # Push the image - if '/' in self.image_name: - push_format_string = 'Pushed image {image_name}' - else: - push_format_string = 'Pushed image {image_name} to {dest}' - self.results['actions'].append(push_format_string.format(image_name=self.image_name, dest=self.push_args['dest'])) - self.results['changed'] = True - if not self.module.check_mode: - self.results['image'], output = self.push_image() - self.results['stdout'] += "\n" + output + self.results['image'], output = self.push_image() + self.results['stdout'] += "\n" + output if image and not self.results.get('image'): self.results['image'] = image @@ -787,45 +780,44 @@ def push_image(self): # Build the destination argument dest = self.push_args.get('dest') - dest_format_string = '{dest}/{image_name}' - regexp = re.compile(r'/{name}(:{tag})?'.format(name=self.name, tag=self.tag)) - if not dest: - if '/' not in self.name: - self.module.fail_json(msg="'push_args['dest']' is required when pushing images that do not have the remote registry in the image name") - - # If the push destination contains the image name and/or the tag - # remove it and warn since it's not needed. - elif regexp.search(dest): - dest = regexp.sub('', dest) - self.module.warn("Image name and tag are automatically added to push_args['dest']. Destination changed to {dest}".format(dest=dest)) + transport = self.push_args.get('transport') - if dest and dest.endswith('/'): - dest = dest[:-1] + if dest is None: + dest = self.image_name - transport = self.push_args.get('transport') if transport: - if not dest: - self.module.fail_json("'push_args['transport'] requires 'push_args['dest'] but it was not provided.") if transport == 'docker': dest_format_string = '{transport}://{dest}' elif transport == 'ostree': dest_format_string = '{transport}:{name}@{dest}' else: dest_format_string = '{transport}:{dest}' - - dest_string = dest_format_string.format(transport=transport, name=self.name, dest=dest, image_name=self.image_name,) - - # Only append the destination argument if the image name is not a URL - if '/' not in self.name: - args.append(dest_string) - - rc, out, err = self._run(args, ignore_errors=True) - if rc != 0: - self.module.fail_json(msg="Failed to push image {image_name}: {err}".format(image_name=self.image_name, err=err)) - last_id = self._get_id_from_output( - out + err, contains=':', split_on=':') - - return self.inspect_image(last_id), out + err + if transport == 'docker-daemon' and ":" not in dest: + dest_format_string = '{transport}:{dest}:latest' + dest_string = dest_format_string.format(transport=transport, name=self.name, dest=dest) + else: + dest_string = dest + + if "/" not in dest_string and "@" not in dest_string and "docker-daemon" not in dest_string: + self.module.fail_json(msg="Destination must be a full URL or path to a directory.") + + args.append(dest_string) + self.module.log("PODMAN-IMAGE-DEBUG: Pushing image {image_name} to {dest_string}".format( + image_name=self.image_name, dest_string=dest_string)) + self.results['actions'].append(" ".join(args)) + self.results['podman_actions'].append(" ".join([self.executable] + args)) + self.results['changed'] = True + out, err = '', '' + if not self.module.check_mode: + rc, out, err = self._run(args, ignore_errors=True) + if rc != 0: + self.module.fail_json(msg="Failed to push image {image_name}".format( + image_name=self.image_name), + stdout=out, stderr=err, + actions=self.results['actions'], + podman_actions=self.results['podman_actions']) + + return self.inspect_image(self.image_name), out + err def remove_image(self, image_name=None): if image_name is None: @@ -922,6 +914,7 @@ def main(): 'docker-daemon', 'oci-archive', 'ostree', + 'docker' ] ), ), diff --git a/tests/integration/targets/podman_image/tasks/idem_push.yml b/tests/integration/targets/podman_image/tasks/idem_push.yml new file mode 100644 index 00000000..93d3ea92 --- /dev/null +++ b/tests/integration/targets/podman_image/tasks/idem_push.yml @@ -0,0 +1,488 @@ +--- +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + ignore_errors: true + register: img_result1 + +- name: Check outputs + assert: + that: + - img_result1 is failed + - "'Destination must be a full URL or path to a directory' in img_result1.msg" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + ignore_errors: true + register: img_result2 + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result2.stderr" + - "'push quay.io/testing/testimage:latest quay.io/testing/testimage:latest' in img_result2.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage:draft + pull: false + push: true + ignore_errors: true + register: img_result2a + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result2a.stderr" + - "'push quay.io/testing/testimage:draft quay.io/testing/testimage:draft' in img_result2a.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: quay.io/testing/testimage + ignore_errors: true + register: img_result3 + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result3.stderr" + - "'push quay.io/testing/testimage:latest quay.io/testing/testimage' in img_result3.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage:draft + pull: false + push: true + push_args: + dest: quay.io/testing/testimage + ignore_errors: true + register: img_result3a + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result3a.stderr" + - "'push quay.io/testing/testimage:draft quay.io/testing/testimage' in img_result3a.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage:draft + pull: false + push: true + push_args: + dest: quay.io/testing/testimage:nodraft + ignore_errors: true + register: img_result3b + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result3b.stderr" + - "'push quay.io/testing/testimage:draft quay.io/testing/testimage:nodraft' in img_result3b.actions" + +- containers.podman.podman_image: + name: testimage2 + tag: testtag + pull: false + push: true + push_args: + dest: quay.io/testing/testimage + ignore_errors: true + register: img_result4 + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result4.stderr" + - "'push testimage2:testtag quay.io/testing/testimage' in img_result4.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: /tmp/testimage-dir + transport: dir + ignore_errors: true + register: img_result5 + +- name: Check outputs + assert: + that: + - img_result5 is changed + - "'push testimage2:latest dir:/tmp/testimage-dir' in img_result5.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: dir:/tmp/testimage-dir1 + ignore_errors: true + register: img_result6 + +- name: Check outputs + assert: + that: + - img_result6 is changed + - "'push testimage2:latest dir:/tmp/testimage-dir1' in img_result6.actions" + +- name: Remove directories + file: + path: "{{ item }}" + state: absent + loop: + - /tmp/test-docker-arch + - /tmp/test-docker-arch1 + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: /tmp/test-docker-arch + transport: docker-archive + ignore_errors: true + register: img_result7 + +- name: Check outputs + assert: + that: + - img_result7 is changed + - "'push testimage2:latest docker-archive:/tmp/test-docker-arch' in img_result7.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: docker-archive:/tmp/test-docker-arch1 + ignore_errors: true + register: img_result8 + +- name: Check outputs + assert: + that: + - img_result8 is changed + - "'push testimage2:latest docker-archive:/tmp/test-docker-arch1' in img_result8.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: /tmp/test-oci-arch + transport: oci-archive + ignore_errors: true + register: img_result9 + +- name: Check outputs + assert: + that: + - img_result9 is changed + - "'push testimage2:latest oci-archive:/tmp/test-oci-arch' in img_result9.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: oci-archive:/tmp/test-oci-arch1 + ignore_errors: true + register: img_result10 + +- name: Check outputs + assert: + that: + - img_result10 is changed + - "'push testimage2:latest oci-archive:/tmp/test-oci-arch1' in img_result10.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: quay.io/testing/testimage1 + transport: docker + ignore_errors: true + register: img_result11 + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result11.stderr" + - "'push testimage2:latest docker://quay.io/testing/testimage1' in img_result11.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: docker://quay.io/testing/testimage22 + ignore_errors: true + register: img_result12 + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result12.stderr" + - "'push testimage2:latest docker://quay.io/testing/testimage22' in img_result12.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: dockerimage + transport: docker-daemon + ignore_errors: true + register: img_result13 + +- name: Check outputs + assert: + that: + - img_result13 is changed + - "'push testimage2:latest docker-daemon:dockerimage:latest' in img_result13.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: docker-daemon:dockerimage2 + ignore_errors: true + register: img_result14 + +- name: Check outputs + assert: + that: + - img_result14 is failure + - "'push testimage2:latest docker-daemon:dockerimage2' in img_result14.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: dockerimage:tagged1 + transport: docker-daemon + ignore_errors: true + register: img_result15 + +- name: Check outputs + assert: + that: + - img_result15 is success + - "'push testimage2:latest docker-daemon:dockerimage:tagged1' in img_result15.actions" + +- containers.podman.podman_image: + name: testimage2 + pull: false + push: true + push_args: + dest: docker-daemon:dockerimage:tagged + ignore_errors: true + register: img_result16 + +- name: Check outputs + assert: + that: + - img_result16 is success + - "'push testimage2:latest docker-daemon:dockerimage:tagged' in img_result16.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: /tmp/testimage-dir25 + transport: dir + ignore_errors: true + register: img_result17 + +- name: Check outputs + assert: + that: + - img_result17 is success + - "'push quay.io/testing/testimage:latest dir:/tmp/testimage-dir25' in img_result17.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: dir:/tmp/testimage-dir15 + ignore_errors: true + register: img_result18 + +- name: Check outputs + assert: + that: + - img_result18 is success + - "'push quay.io/testing/testimage:latest dir:/tmp/testimage-dir15' in img_result18.actions" + +- name: Remove directories for docker-archive + file: + path: "{{ item }}" + state: absent + loop: + - /tmp/test-docker-arch5 + - /tmp/test-docker-arch15 + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: /tmp/test-docker-arch5 + transport: docker-archive + ignore_errors: true + register: img_result19 + +- name: Check outputs + assert: + that: + - img_result19 is success + - "'push quay.io/testing/testimage:latest docker-archive:/tmp/test-docker-arch5' in img_result19.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: docker-archive:/tmp/test-docker-arch15 + ignore_errors: true + register: img_result20 + +- name: Check outputs + assert: + that: + - img_result20 is success + - "'push quay.io/testing/testimage:latest docker-archive:/tmp/test-docker-arch15' in img_result20.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: /tmp/test-oci-arch5 + transport: oci-archive + ignore_errors: true + register: img_result21 + +- name: Check outputs + assert: + that: + - img_result21 is success + - "'push quay.io/testing/testimage:latest oci-archive:/tmp/test-oci-arch5' in img_result21.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: oci-archive:/tmp/test-oci-arch15 + ignore_errors: true + register: img_result22 + +- name: Check outputs + assert: + that: + - img_result22 is success + - "'push quay.io/testing/testimage:latest oci-archive:/tmp/test-oci-arch15' in img_result22.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: quay.io/testing/testimage5 + transport: docker + ignore_errors: true + register: img_result23 + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result23.stderr" + - "'push quay.io/testing/testimage:latest docker://quay.io/testing/testimage5' in img_result23.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: docker://quay.io/testing/testimage22 + ignore_errors: true + register: img_result24 + +- name: Check outputs + assert: + that: + - "'authentication required' in img_result24.stderr" + - "'push quay.io/testing/testimage:latest docker://quay.io/testing/testimage22' in img_result24.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: dockerimage5 + transport: docker-daemon + ignore_errors: true + register: img_result25 + +- name: Check outputs + assert: + that: + - img_result25 is success + - "'push quay.io/testing/testimage:latest docker-daemon:dockerimage5:latest' in img_result25.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: docker-daemon:dockerimage25 + ignore_errors: true + register: img_result26 + +- name: Check outputs + assert: + that: + - img_result26 is failed + - "'push quay.io/testing/testimage:latest docker-daemon:dockerimage25' in img_result26.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: dockerimage:tagged15 + transport: docker-daemon + ignore_errors: true + register: img_result27 + +- name: Check outputs + assert: + that: + - img_result27 is success + - "'push quay.io/testing/testimage:latest docker-daemon:dockerimage:tagged15' in img_result27.actions" + +- containers.podman.podman_image: + name: quay.io/testing/testimage + pull: false + push: true + push_args: + dest: docker-daemon:dockerimage:tagged5 + ignore_errors: true + register: img_result28 + +- name: Check outputs + assert: + that: + - img_result28 is success + - "'push quay.io/testing/testimage:latest docker-daemon:dockerimage:tagged5' in img_result28.actions" diff --git a/tests/integration/targets/podman_image/tasks/main.yml b/tests/integration/targets/podman_image/tasks/main.yml index f5c3ddf4..c2ddfb45 100644 --- a/tests/integration/targets/podman_image/tasks/main.yml +++ b/tests/integration/targets/podman_image/tasks/main.yml @@ -227,7 +227,7 @@ file: /var/tmp/build/Dockerfile register: oci_build5 - - name: Build OCI image, point to location of Containerfile and path + - name: Build OCI image with no Containerfile and path containers.podman.podman_image: executable: "{{ test_executable | default('podman') }}" name: testimage5x @@ -350,6 +350,28 @@ - item.Architecture == "arm" loop: "{{ imageinfo_arch.images }}" + - name: Build Docker image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/testing/testimage + path: /var/tmp/build + register: build_image1 + + - name: Build Docker image - 2 + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: quay.io/testing/testimage:draft + path: /var/tmp/build + + - name: Build Docker image + containers.podman.podman_image: + executable: "{{ test_executable | default('podman') }}" + name: testimage2:testtag + path: /var/tmp/build + register: build_image2 + + - include_tasks: idem_push.yml + - name: Create a Quadlet for image with filename containers.podman.podman_image: executable: "{{ test_executable | default('podman') }}" @@ -490,4 +512,8 @@ - quay.io/coreos/etcd:v3.3.11 - localhost/testimage - localhost/testimage2 + - localhost/testimage2:testtag + - localhost/testimage3 - localhost/dockerimage + - quay.io/testing/testimage + - quay.io/testing/testimage:draft