diff --git a/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/cosa_v1.go b/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/cosa_v1.go index 752888a91f..30a7908aa5 100644 --- a/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/cosa_v1.go +++ b/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/cosa_v1.go @@ -1,7 +1,7 @@ package builds // generated by 'make schema' -// source hash: 3508b2f150e72b8e24151d870789809cf4070cec6b4716966a4e8bc585e0c5f1 +// source hash: 1e32ab25dfdd0724f8e8246008b9d91b88a40e9ea834cf779ab0da818bf1cf25 type AdvisoryDiff []AdvisoryDiffItems @@ -27,10 +27,6 @@ type Artifact struct { UncompressedSize int `json:"uncompressed-size,omitempty"` } -type BaseOsContainer struct { - Image string `json:"image"` -} - type Build struct { AdvisoryDiffAgainstParent AdvisoryDiff `json:"parent-advisories-diff,omitempty"` AdvisoryDiffBetweenBuilds AdvisoryDiff `json:"advisories-diff,omitempty"` @@ -38,7 +34,7 @@ type Build struct { Amis []Amis `json:"amis,omitempty"` Architecture string `json:"coreos-assembler.basearch,omitempty"` Azure *Cloudartifact `json:"azure,omitempty"` - BaseOsContainer *BaseOsContainer `json:"base-oscontainer,omitempty"` + BaseOsContainer *Image `json:"base-oscontainer,omitempty"` BuildArtifacts *BuildArtifacts `json:"images,omitempty"` BuildID string `json:"buildid"` BuildRef string `json:"ref,omitempty"` @@ -54,7 +50,7 @@ type Build struct { CosaImageChecksum string `json:"coreos-assembler.image-config-checksum,omitempty"` CosaImageVersion int `json:"coreos-assembler.image-genver,omitempty"` Extensions *Extensions `json:"extensions,omitempty"` - ExtensionsContainer *ExtensionsContainer `json:"extensions-container,omitempty"` + ExtensionsContainer *Image `json:"extensions-container,omitempty"` FedoraCoreOsParentCommit string `json:"fedora-coreos.parent-commit,omitempty"` FedoraCoreOsParentVersion string `json:"fedora-coreos.parent-version,omitempty"` Gcp *Gcp `json:"gcp,omitempty"` @@ -134,10 +130,6 @@ type Extensions struct { Sha256 string `json:"sha256"` } -type ExtensionsContainer struct { - Image string `json:"image"` -} - type Gcp struct { ImageFamily string `json:"family,omitempty"` ImageName string `json:"image"` @@ -154,7 +146,7 @@ type Git struct { type Image struct { Comment string `json:"comment,omitempty"` - Digest string `json:"digest"` + Digest string `json:"digest,omitempty"` Image string `json:"image"` } diff --git a/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/schema_doc.go b/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/schema_doc.go index 7c8f985691..936d80cc06 100644 --- a/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/schema_doc.go +++ b/mantle/vendor/github.com/coreos/coreos-assembler/pkg/builds/schema_doc.go @@ -1,5 +1,5 @@ // Generated by ./generate-schema.sh -// Source hash: 3508b2f150e72b8e24151d870789809cf4070cec6b4716966a4e8bc585e0c5f1 +// Source hash: 1e32ab25dfdd0724f8e8246008b9d91b88a40e9ea834cf779ab0da818bf1cf25 // DO NOT EDIT package builds @@ -56,10 +56,10 @@ var generatedSchemaJSON = `{ "image": { "type": "object", "required": [ - "digest", "image" ], "optional": [ + "digest", "comment" ], "properties": { @@ -882,31 +882,13 @@ var generatedSchemaJSON = `{ "$id": "#/properties/base-oscontainer", "type": "object", "title": "Base OS container", - "required": [ - "image" - ], - "properties": { - "image": { - "$id": "#/properties/base-oscontainer/image", - "type": "string", - "title": "Image" - } - } + "$ref": "#/definitions/image" }, "extensions-container": { "$id": "#/properties/extensions-container", "type": "object", "title": "Extensions container", - "required": [ - "image" - ], - "properties": { - "image": { - "$id": "#/properties/extensions-container/image", - "type": "string", - "title": "Image" - } - } + "$ref": "#/definitions/image" }, "gcp": { "$id": "#/properties/gcp", diff --git a/pkg/builds/cosa_v1.go b/pkg/builds/cosa_v1.go index 752888a91f..30a7908aa5 100644 --- a/pkg/builds/cosa_v1.go +++ b/pkg/builds/cosa_v1.go @@ -1,7 +1,7 @@ package builds // generated by 'make schema' -// source hash: 3508b2f150e72b8e24151d870789809cf4070cec6b4716966a4e8bc585e0c5f1 +// source hash: 1e32ab25dfdd0724f8e8246008b9d91b88a40e9ea834cf779ab0da818bf1cf25 type AdvisoryDiff []AdvisoryDiffItems @@ -27,10 +27,6 @@ type Artifact struct { UncompressedSize int `json:"uncompressed-size,omitempty"` } -type BaseOsContainer struct { - Image string `json:"image"` -} - type Build struct { AdvisoryDiffAgainstParent AdvisoryDiff `json:"parent-advisories-diff,omitempty"` AdvisoryDiffBetweenBuilds AdvisoryDiff `json:"advisories-diff,omitempty"` @@ -38,7 +34,7 @@ type Build struct { Amis []Amis `json:"amis,omitempty"` Architecture string `json:"coreos-assembler.basearch,omitempty"` Azure *Cloudartifact `json:"azure,omitempty"` - BaseOsContainer *BaseOsContainer `json:"base-oscontainer,omitempty"` + BaseOsContainer *Image `json:"base-oscontainer,omitempty"` BuildArtifacts *BuildArtifacts `json:"images,omitempty"` BuildID string `json:"buildid"` BuildRef string `json:"ref,omitempty"` @@ -54,7 +50,7 @@ type Build struct { CosaImageChecksum string `json:"coreos-assembler.image-config-checksum,omitempty"` CosaImageVersion int `json:"coreos-assembler.image-genver,omitempty"` Extensions *Extensions `json:"extensions,omitempty"` - ExtensionsContainer *ExtensionsContainer `json:"extensions-container,omitempty"` + ExtensionsContainer *Image `json:"extensions-container,omitempty"` FedoraCoreOsParentCommit string `json:"fedora-coreos.parent-commit,omitempty"` FedoraCoreOsParentVersion string `json:"fedora-coreos.parent-version,omitempty"` Gcp *Gcp `json:"gcp,omitempty"` @@ -134,10 +130,6 @@ type Extensions struct { Sha256 string `json:"sha256"` } -type ExtensionsContainer struct { - Image string `json:"image"` -} - type Gcp struct { ImageFamily string `json:"family,omitempty"` ImageName string `json:"image"` @@ -154,7 +146,7 @@ type Git struct { type Image struct { Comment string `json:"comment,omitempty"` - Digest string `json:"digest"` + Digest string `json:"digest,omitempty"` Image string `json:"image"` } diff --git a/pkg/builds/schema_doc.go b/pkg/builds/schema_doc.go index 7c8f985691..936d80cc06 100644 --- a/pkg/builds/schema_doc.go +++ b/pkg/builds/schema_doc.go @@ -1,5 +1,5 @@ // Generated by ./generate-schema.sh -// Source hash: 3508b2f150e72b8e24151d870789809cf4070cec6b4716966a4e8bc585e0c5f1 +// Source hash: 1e32ab25dfdd0724f8e8246008b9d91b88a40e9ea834cf779ab0da818bf1cf25 // DO NOT EDIT package builds @@ -56,10 +56,10 @@ var generatedSchemaJSON = `{ "image": { "type": "object", "required": [ - "digest", "image" ], "optional": [ + "digest", "comment" ], "properties": { @@ -882,31 +882,13 @@ var generatedSchemaJSON = `{ "$id": "#/properties/base-oscontainer", "type": "object", "title": "Base OS container", - "required": [ - "image" - ], - "properties": { - "image": { - "$id": "#/properties/base-oscontainer/image", - "type": "string", - "title": "Image" - } - } + "$ref": "#/definitions/image" }, "extensions-container": { "$id": "#/properties/extensions-container", "type": "object", "title": "Extensions container", - "required": [ - "image" - ], - "properties": { - "image": { - "$id": "#/properties/extensions-container/image", - "type": "string", - "title": "Image" - } - } + "$ref": "#/definitions/image" }, "gcp": { "$id": "#/properties/gcp", diff --git a/src/cmd-push-container b/src/cmd-push-container index 2a8a8b5e95..ba1ddec687 100755 --- a/src/cmd-push-container +++ b/src/cmd-push-container @@ -68,7 +68,10 @@ with tempfile.NamedTemporaryFile(dir='tmp', prefix='push-container-digestfile') container = 'base-oscontainer' if args.image != 'ostree': container = args.image - meta[container] = {'image': f"{container_name}@{digest}"} + meta[container] = { + 'image': container_name, + 'digest': digest + } metapath_new = f"{metapath}.new" with open(metapath_new, 'w') as f: json.dump(meta, f, sort_keys=True) diff --git a/src/cmd-push-container-manifest b/src/cmd-push-container-manifest index 61570ec12b..fa11975e11 100755 --- a/src/cmd-push-container-manifest +++ b/src/cmd-push-container-manifest @@ -6,7 +6,6 @@ import argparse import os import sys -import tempfile from cosalib.container_manifest import create_and_push_container_manifest from cosalib.builds import Builds from cosalib.meta import GenericBuildMeta @@ -22,7 +21,7 @@ def main(): if args.images: # User provided images directly create_and_push_container_manifest( - args.repo, args.tag, args.images, args.v2s2, None) + args.repo, args.tags, args.images, args.v2s2) else: # Picking up images from artifacts in meta.json builds = Builds() @@ -60,16 +59,24 @@ def main(): images.append(f"oci-archive:{ociarchive}") # Create/Upload the manifest list to the container registry - with tempfile.NamedTemporaryFile() as digestfile: - create_and_push_container_manifest( - args.repo, args.tag, images, args.v2s2, digestfile.name) - digestfile.seek(0) - digest = digestfile.read().decode('utf-8').strip() + manifest_info = create_and_push_container_manifest( + args.repo, args.tags, images, args.v2s2) - # Update the meta.json in each build/arch metadata - for _, buildmeta in buildmetas.items(): - buildmeta[args.metajsonname] = {'image': f"{args.repo}@{digest}"} - buildmeta.write(artifact_name=args.metajsonname) + # 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'] + } + buildmetas[arch].write(artifact_name=args.metajsonname) def parse_args(): @@ -95,10 +102,11 @@ Examples: --repo quay.io/dustymabe/fedora-coreos --tag stable --artifact=ostree \\ --metajsonname=base-oscontainer --build=latest --arch=x86_64 --arch=aarch64""") parser.add_argument("--repo", required=True, help="The registry repo to target for the manifest") - parser.add_argument("--tag", required=True, help="The tag of the manifest to use") + parser.add_argument("--tag", required=True, dest='tags', action='append', + help="The tag of the manifest to use") parser.add_argument("--authfile", help="A file to use for registry auth") parser.add_argument('--v2s2', action='store_true', - help='Use old image manifest version2 schema 2 format') + help='Use old image manifest version 2 schema 2 format') group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--image", dest='images', action='append', default=[], @@ -112,7 +120,7 @@ Examples: parser.add_argument("--arch", dest='arches', action='append', default=[], help="""Limit the architectures to upload to the specificed set (otherwise it defaults to all available for that build). Can be - specificed multiple times like: --arch x86_64 --arch aarch64""") + specified multiple times like: --arch x86_64 --arch aarch64""") parser.add_argument("--metajsonname", help="The name under which to store the container information in meta.json") return parser.parse_args() diff --git a/src/cosalib/container_manifest.py b/src/cosalib/container_manifest.py index 0b5ab885a2..56538174ca 100644 --- a/src/cosalib/container_manifest.py +++ b/src/cosalib/container_manifest.py @@ -1,9 +1,11 @@ +import json + from cosalib.cmdlib import runcmd -def create_local_container_manifest(repo, tag, images): +def create_local_container_manifest(repo, tag, images) -> dict: ''' - Create local manifest list + Create local manifest list and return the final manifest JSON @param images list of image specifications (including transport) @param repo str registry repository @param tag str manifest tag @@ -13,6 +15,9 @@ def create_local_container_manifest(repo, tag, images): for image in images: cmd = ["podman", "manifest", "add", f"{repo}:{tag}", image] runcmd(cmd) + manifest_info = runcmd(["podman", "manifest", "inspect", f"{repo}:{tag}"], + capture_output=True).stdout + return json.loads(manifest_info) def delete_local_container_manifest(repo, tag): @@ -25,35 +30,33 @@ def delete_local_container_manifest(repo, tag): runcmd(cmd) -def push_container_manifest(repo, tag, digestfile, v2s2=False): +def push_container_manifest(repo, tags, v2s2=False): ''' Push manifest to registry @param repo str registry repository - @param tag str manifest tag - @param digestfile str write container digest to file + @param tags list of tags to push @param v2s2 boolean use to force v2s2 format ''' - cmd = ["podman", "manifest", "push", - "--all", f"{repo}:{tag}", f"{repo}:{tag}"] + base_cmd = ["podman", "manifest", "push", "--all", f"{repo}:{tags[0]}"] if v2s2: # `--remove-signatures -f v2s2` is a workaround for when you try # to create a manifest with 2 different mediaType. It seems to be # a Quay issue. - cmd.extend(["--remove-signatures", "-f", "v2s2"]) - if digestfile: - cmd.extend([f"--digestfile={digestfile}"]) - runcmd(cmd) + base_cmd.extend(["--remove-signatures", "-f", "v2s2"]) + runcmd(base_cmd + [f"{repo}:{tags[0]}"]) + for tag in tags[1:]: + runcmd(base_cmd + [f"{repo}:{tag}"]) -def create_and_push_container_manifest(repo, tag, images, v2s2, digestfile): +def create_and_push_container_manifest(repo, tags, images, v2s2) -> dict: ''' - Do it all! Create, Push, Cleanup + Do it all! Create, push, cleanup, and return the final manifest JSON. @param repo str registry repository - @param tag str manifest tag + @param tags list of tags @param images list of image specifications (including transport) @param v2s2 boolean use to force v2s2 format - @param digestfile str write container digest to file ''' - create_local_container_manifest(repo, tag, images) - push_container_manifest(repo, tag, digestfile, v2s2) - delete_local_container_manifest(repo, tag) + manifest_info = create_local_container_manifest(repo, tags[0], images) + push_container_manifest(repo, tags, v2s2) + delete_local_container_manifest(repo, tags[0]) + return manifest_info diff --git a/src/v1.json b/src/v1.json index 0c3a3fa92e..827723cc7b 100644 --- a/src/v1.json +++ b/src/v1.json @@ -50,10 +50,10 @@ "image": { "type": "object", "required": [ - "digest", "image" ], "optional": [ + "digest", "comment" ], "properties": { @@ -876,31 +876,13 @@ "$id": "#/properties/base-oscontainer", "type": "object", "title": "Base OS container", - "required": [ - "image" - ], - "properties": { - "image": { - "$id": "#/properties/base-oscontainer/image", - "type": "string", - "title": "Image" - } - } + "$ref": "#/definitions/image" }, "extensions-container": { "$id": "#/properties/extensions-container", "type": "object", "title": "Extensions container", - "required": [ - "image" - ], - "properties": { - "image": { - "$id": "#/properties/extensions-container/image", - "type": "string", - "title": "Image" - } - } + "$ref": "#/definitions/image" }, "gcp": { "$id": "#/properties/gcp",