diff --git a/src/cmd-push-container-manifest b/src/cmd-push-container-manifest index eb31b23a6c..c67861567b 100755 --- a/src/cmd-push-container-manifest +++ b/src/cmd-push-container-manifest @@ -4,11 +4,13 @@ # arguments provided by the user. import argparse +import json import os 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__))) @@ -16,6 +18,10 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) def main(): args = parse_args() + map_arch = {} + map_arch['arm64'] = 'aarch64' + map_arch['amd64'] = 'x86_64' + if args.authfile: os.environ["REGISTRY_AUTH_FILE"] = args.authfile if args.images: @@ -37,6 +43,19 @@ def main(): # - Store the path to the container image in the container_images list images = [] buildmetas = dict() + digests = {} + upload = False + # Checks if we already have it in the remote + cmd = ["skopeo", "inspect", "--raw", f"docker://{args.repo}:{args.tags[0]}"] + manifest_meta = runcmd(cmd, capture_output=True, check=False).stdout + if manifest_meta: + manifests = json.loads(manifest_meta) + for manifest in manifests['manifests']: + arch = manifest['platform']['architecture'] + if arch in map_arch: + arch = map_arch[arch] + digests[arch] = manifest['digest'] + for arch in args.arches: if arch not in build_arches: print(f"Requested architecture {arch} is not in {args.build}") @@ -48,6 +67,14 @@ 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 matches each arch digest in the remote + if 'digest' in buildmetas[arch][args.metajsonname]: + digest = buildmetas[arch][args.metajsonname]['digest'] + if arch not in digests: + upload = True + elif digest != digests[arch]: + upload = True ociarchive = os.path.join(builddir, buildmeta['images'][args.artifact]['path']) ocisha256sum = buildmeta['images'][args.artifact]['sha256'] if not os.path.exists(ociarchive): @@ -58,26 +85,25 @@ 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 in map_arch: + arch = map_arch[arch] + buildmetas[arch][args.metajsonname] = { + 'image': args.repo, + 'digest': manifest['digest'], + 'tags': args.tags + } + buildmetas[arch].write(artifact_name=args.metajsonname) def parse_args(): @@ -108,6 +134,7 @@ Examples: parser.add_argument("--authfile", help="A file to use for registry auth") parser.add_argument('--v2s2', action='store_true', help='Use old image manifest version 2 schema 2 format') + parser.add_argument("--force", help="Force manifest overwriting", action='store_true') group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--image", dest='images', action='append', default=[],