From cce242851e83b7e06a3b773706b4b2050d6b5f34 Mon Sep 17 00:00:00 2001 From: Renata Ravanelli Date: Tue, 1 Nov 2022 10:57:42 -0300 Subject: [PATCH] Fix #3150 - Make push-container-manifest idempotent - Check if the digests are already present in the remote manifest and if you want to force or not a new manifest upload Signed-off-by: Renata Ravanelli --- src/cmd-push-container-manifest | 59 ++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/cmd-push-container-manifest b/src/cmd-push-container-manifest index eb31b23a6c..f5829e59d7 100755 --- a/src/cmd-push-container-manifest +++ b/src/cmd-push-container-manifest @@ -9,6 +9,7 @@ import sys from cosalib.container_manifest import create_and_push_container_manifest from cosalib.builds import Builds from cosalib.meta import GenericBuildMeta +from cosalib.cmdlib import runcmd from cosalib.cmdlib import sha256sum_file sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) @@ -37,6 +38,16 @@ def main(): # - Store the path to the container image in the container_images list images = [] buildmetas = dict() + upload = False + check_digest = "" + + # Checks if we already have it in the remote + try: + cmd = ["skopeo", "inspect","--raw", f"docker://{args.repo}:{args.tags[0]}"] + check_digest = runcmd(cmd, capture_output=True).stdout + except: + pass + for arch in args.arches: if arch not in build_arches: print(f"Requested architecture {arch} is not in {args.build}") @@ -48,6 +59,13 @@ def main(): if not buildmeta['images'][args.artifact]: print(f"No artifact {args.artifact} in {args.build}/{arch}") raise Exception + # Checks if the meta digest is present and if it matches the arch digest in the remote + try: + digest = buildmetas[arch][args.metajsonname]['digest'] + if digest not in str(check_digest) + upload = True + except: + pass ociarchive = os.path.join(builddir, buildmeta['images'][args.artifact]['path']) ocisha256sum = buildmeta['images'][args.artifact]['sha256'] if not os.path.exists(ociarchive): @@ -58,26 +76,27 @@ def main(): raise Exception images.append(f"oci-archive:{ociarchive}") - # Create/Upload the manifest list to the container registry - manifest_info = create_and_push_container_manifest( - args.repo, args.tags, images, args.v2s2) - - # Update the `meta.json` files. Note the digest included is the - # arch-specific one for each individual arch, and not the manifest list - # digest. See: https://github.com/coreos/coreos-assembler/issues/3122. - assert len(manifest_info['manifests']) == len(buildmetas) - for manifest in manifest_info['manifests']: - arch = manifest['platform']['architecture'] - if arch == 'arm64': - arch = 'aarch64' - elif arch == 'amd64': - arch = 'x86_64' - buildmetas[arch][args.metajsonname] = { - 'image': args.repo, - 'digest': manifest['digest'], - 'tags': args.tags - } - buildmetas[arch].write(artifact_name=args.metajsonname) + if upload is True or args.force is True: + # Create/Upload the manifest list to the container registry + manifest_info = create_and_push_container_manifest( + args.repo, args.tags, images, args.v2s2) + + # Update the `meta.json` files. Note the digest included is the + # arch-specific one for each individual arch, and not the manifest list + # digest. See: https://github.com/coreos/coreos-assembler/issues/3122. + assert len(manifest_info['manifests']) == len(buildmetas) + for manifest in manifest_info['manifests']: + arch = manifest['platform']['architecture'] + if arch == 'arm64': + arch = 'aarch64' + elif arch == 'amd64': + arch = 'x86_64' + buildmetas[arch][args.metajsonname] = { + 'image': args.repo, + 'digest': manifest['digest'], + 'tags': args.tags + } + buildmetas[arch].write(artifact_name=args.metajsonname) def parse_args():