From 188c22cc5e3ae797e1f30cb49fb6e5f944ff68ed Mon Sep 17 00:00:00 2001 From: Clement Verna Date: Aug 12 2018 19:10:57 +0000 Subject: Add python script to generate manifest list. The manifest-tool binary does not work if we use the certs to authenticate. This commit adds a script that creates and push the manifest list to the registry. Signed-off-by: Clement Verna --- diff --git a/scripts/container-manifest/manifest.yaml b/scripts/container-manifest/manifest.yaml deleted file mode 100644 index 617d2af..0000000 --- a/scripts/container-manifest/manifest.yaml +++ /dev/null @@ -1,29 +0,0 @@ -image: {registry}.fedoraproject.org/{image}:{tag} -tags: ['{tag}', '{tag-name}'] -manifests: - - image: {registry}.fedoraproject.org/{image}:{tag}-armhfp - platform: - architecture: arm - variant: v7 - os: linux - - - image: {registry}.fedoraproject.org/{image}:{tag}-aarch64 - platform: - architecture: arm64 - variant: v8 - os: linux - - - image: {registry}.fedoraproject.org/{image}:{tag}-x86_64 - platform: - architecture: amd64 - os: linux - - - image: {registry}.fedoraproject.org/{image}:{tag}-ppc64le - platform: - architecture: ppc64le - os: linux - - - image: {registry}.fedoraproject.org/{image}:{tag}-s390x - platform: - architecture: s390x - os: linux diff --git a/scripts/generate-manifest-list.py b/scripts/generate-manifest-list.py new file mode 100644 index 0000000..3f14e12 --- /dev/null +++ b/scripts/generate-manifest-list.py @@ -0,0 +1,116 @@ +#!/usr/bin/python3 +# +# generate-manifest-list.py - A script used to create and push the container base image +# manifest list used for mutli arch support +# This is used by sync-latest-container-base-image.sh script +# +# Authors: +# Clement Verna +# Copyright (C) 2018 Red Hat Inc, +# SPDX-License-Identifier: GPL-2.0+ +import argparse +import json +from functools import wraps + +import requests + + +MEDIA_TYPE_LIST_V2 = "application/vnd.docker.distribution.manifest.list.v2+json" + +MANIFEST_LIST = {"schemaVersion": 2, "mediaType": MEDIA_TYPE_LIST_V2, "manifests": []} + +ARCHES = ["x86_64", "aarch64", "armhfp", "ppc64le", "s390x"] + + +def certs(function): + """ Decorator that create the certificate path based + on the registry name """ + + @wraps(function) + def get_certs_path(*args, **kwargs): + cert_path = f"/etc/docker/certs.d/{kwargs['registry']}/client.cert" + cert_key = f"/etc/docker/certs.d/{kwargs['registry']}/client.key" + kwargs["cert"] = (cert_path, cert_key) + return function(*args, **kwargs) + + return get_certs_path + + +@certs +def create_image_manifest(tag, name, registry, cert): + """ Get the manifest for a specific image and returns the data + needed to build the manifest list """ + + image = None + headers = {"Accept": "application/vnd.docker.distribution.manifest.v2+json"} + res = requests.get( + f"https://{registry}/v2/{name}/manifests/{tag}", cert=cert, headers=headers + ) + + if res.ok: + data = res.json() + image = { + "mediaType": res.headers["Content-Type"], + "size": int(res.headers["Content-Length"]), + "digest": res.headers["Docker-Content-Digest"], + "platform": {"architecture": "", "os": "linux"}, + } + + return image + + +@certs +def push_manifest_list(manifest_list, tags, name, registry, cert): + """ Push the manifest list to the correct tags """ + + headers = {"Content-Type": MEDIA_TYPE_LIST_V2} + + for tag in tags: + res = requests.put( + f"https://{registry}/v2/{name}/manifests/{tag}", + data=json.dumps(manifest_list), + headers=headers, + cert=cert, + ) + + if not res.ok: + print(f"ERROR: Failed to push the manifest list : {res.text}") + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser() + parser.add_argument( + "--release", "-r", help="number of the fedora release", required=True + ) + parser.add_argument( + "--registry", + help="name of the container registry", + default="registry.fedoraproject.org", + ) + parser.add_argument( + "--tag", help="tag to apply to the container image", default="latest" + ) + parser.add_argument("--image", help="name of the container image", default="fedora") + args = parser.parse_args() + + tags = [f"{args.release}-" + arch for arch in ARCHES] + + for tag in tags: + image = create_image_manifest(tag=tag, name=args.image, registry=args.registry) + if image is not None: + manifest = image.copy() + if "x86_64" in tag: + manifest["platform"]["architecture"] = "amd64" + else: + manifest["platform"]["architecture"] = tag[3:] + MANIFEST_LIST["manifests"].append(manifest) + else: + print(f"ERROR : Could not find the image manifest for fedora:{tag}") + + push_manifest_list( + manifest_list=MANIFEST_LIST, + tags=[args.release, args.tag], + name=args.image, + registry=args.registry, + ) diff --git a/scripts/sync-latest-container-base-image.sh b/scripts/sync-latest-container-base-image.sh index cb42723..805a21a 100755 --- a/scripts/sync-latest-container-base-image.sh +++ b/scripts/sync-latest-container-base-image.sh @@ -89,20 +89,12 @@ if [[ -z "$stage" ]]; then popd &> /dev/null - printf "Create manifest.yaml for fedora\n" - for registry in "registry" "candidate-registry" + for registry in "registry.fedoraproject.org" "candidate-registry.fedoraproject.org" do - cp container-manifest/manifest.yaml container-manifest/manifest-${1}.yaml - sed -i "s|{image}|fedora|g" container-manifest/manifest-${1}.yaml - sed -i "s|{registry}|${registry}|g" container-manifest/manifest-${1}.yaml - sed -i "s|{tag}|${1}|g" container-manifest/manifest-${1}.yaml - sed -i "s|{tag-name}|${tagname}|g" container-manifest/manifest-${1}.yaml - printf "Push manifest to ${registry}\n" - manifest-tool push from-spec container-manifest/manifest-${1}.yaml + python3 generate-manifest-list.py -r ${1} --registry ${registry} --tag ${tagname} --image fedora done printf "Removing temporary directory\n" - rm -f container-manifest/manifest-${1}.yaml rm -rf $work_dir fi if [[ -n ${minimal_build_name} ]]; then @@ -120,21 +112,13 @@ if [[ -z "$stage" ]]; then done popd &> /dev/null - printf "Create manifest.yaml for fedora-minimal\n" - for registry in "registry" "candidate-registry" + for registry in "registry.fedoraproject.org" "candidate-registry.fedoraproject.org" do - cp container-manifest/manifest.yaml container-manifest/manifest-${1}.yaml - sed -i "s|{image}|fedora-minimal|g" container-manifest/manifest-${1}.yaml - sed -i "s|{registry}|${registry}|g" container-manifest/manifest-${1}.yaml - sed -i "s|{tag}|${1}|g" container-manifest/manifest-${1}.yaml - sed -i "s|{tag-name}|${tagname}|g" container-manifest/manifest-${1}.yaml - printf "Push manifest to ${registry}\n" - manifest-tool push from-spec container-manifest/manifest-${1}.yaml + python3 generate-manifest-list.py -r ${1} --registry ${registry} --tag ${tagname} --image fedora-minimal done printf "Removing temporary directory\n" - rm -f container-manifest/manifest-${1}.yaml rm -rf $work_dir fi