Skip to content

Commit

Permalink
cmd-push-container-manifest: attempt to make more idempotent
Browse files Browse the repository at this point in the history
Check if the digests are already present in the remote
manifest and if you want to force or not a new manifest upload.

Fixes coreos#3150

Signed-off-by: Renata Ravanelli <[email protected]>
  • Loading branch information
ravanelli committed Nov 1, 2022
1 parent bc2a455 commit e6da3f7
Showing 1 changed file with 47 additions and 20 deletions.
67 changes: 47 additions & 20 deletions src/cmd-push-container-manifest
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@
# 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__)))


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:
Expand All @@ -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}")
Expand All @@ -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):
Expand All @@ -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():
Expand Down Expand Up @@ -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=[],
Expand Down

0 comments on commit e6da3f7

Please sign in to comment.