From 9ec1b021813259caeb08ed3507401b03d53cd01f Mon Sep 17 00:00:00 2001 From: Mikalai Radchuk <509198+m1kola@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:20:08 +0100 Subject: [PATCH] Fix canonical image ref resolution (#3434) Previously in release scripts we were using `docker inspect` which seems to sort .RepoDigests and it makes selection of the correct digest difficult because platform-specific digest can appear at a different index depending on the digests in the list. Signed-off-by: Mikalai Radchuk --- Makefile | 15 +----- scripts/package_release.sh | 15 ++++++ util/image-canonical-ref/main.go | 78 ++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 14 deletions(-) create mode 100644 util/image-canonical-ref/main.go diff --git a/Makefile b/Makefile index 9a66d119f0..d90bd37006 100644 --- a/Makefile +++ b/Makefile @@ -306,14 +306,8 @@ verify: vendor verify-codegen verify-mockgen verify-manifests #HELP Run all veri #SECTION Release -.PHONY: pull-opm -pull-opm: - docker pull $(OPERATOR_REGISTRY_IMAGE) - .PHONY: package package: $(YQ) $(HELM) #HELP Package OLM for release -package: OLM_RELEASE_IMG_REF=$(shell docker inspect --format='{{index .RepoDigests 0}}' $(IMAGE_REPO):$(RELEASE_VERSION)) -package: OPM_IMAGE_REF=$(shell docker inspect --format='{{index .RepoDigests 0}}' $(OPERATOR_REGISTRY_IMAGE)) package: ifndef TARGET $(error TARGET is undefined) @@ -321,12 +315,6 @@ endif ifndef RELEASE_VERSION $(error RELEASE_VERSION is undefined) endif - @echo "Getting operator registry image" - docker pull $(OPERATOR_REGISTRY_IMAGE) - $(YQ) w -i deploy/$(TARGET)/values.yaml olm.image.ref $(OLM_RELEASE_IMG_REF) - $(YQ) w -i deploy/$(TARGET)/values.yaml catalog.image.ref $(OLM_RELEASE_IMG_REF) - $(YQ) w -i deploy/$(TARGET)/values.yaml package.image.ref $(OLM_RELEASE_IMG_REF) - $(YQ) w -i deploy/$(TARGET)/values.yaml -- catalog.opmImageArgs "--opmImage=$(OPM_IMAGE_REF)" ./scripts/package_release.sh $(RELEASE_VERSION) deploy/$(TARGET)/manifests/$(RELEASE_VERSION) deploy/$(TARGET)/values.yaml ln -sfFn ./$(RELEASE_VERSION) deploy/$(TARGET)/manifests/latest ifeq ($(PACKAGE_QUICKSTART), true) @@ -334,9 +322,8 @@ ifeq ($(PACKAGE_QUICKSTART), true) endif .PHONY: release -release: pull-opm manifests # pull the opm image to get the digest +release: manifests @echo "Generating the $(RELEASE_VERSION) release" - docker pull $(IMAGE_REPO):$(RELEASE_VERSION) $(MAKE) TARGET=upstream RELEASE_VERSION=$(RELEASE_VERSION) PACKAGE_QUICKSTART=true package .PHONY: FORCE diff --git a/scripts/package_release.sh b/scripts/package_release.sh index cd8b722c61..881ff79146 100755 --- a/scripts/package_release.sh +++ b/scripts/package_release.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +set -o errexit +set -o nounset +set -o pipefail + if [[ ${#@} -lt 3 ]]; then echo "Usage: $0 semver chart values" echo "* semver: semver-formatted version for this package" @@ -14,6 +18,17 @@ values=$3 source .bingo/variables.env +OLM_RELEASE_IMG_REF=$(go run util/image-canonical-ref/main.go ${IMAGE_REPO}:${version}) +OPM_IMAGE_REF=$(go run util/image-canonical-ref/main.go ${OPERATOR_REGISTRY_IMAGE}) + +echo "Using OPM image ${OPM_IMAGE_REF}" +echo "Using OLM image ${OLM_RELEASE_IMG_REF}" + +$YQ w -i $values olm.image.ref ${OLM_RELEASE_IMG_REF} +$YQ w -i $values catalog.image.ref ${OLM_RELEASE_IMG_REF} +$YQ w -i $values package.image.ref ${OLM_RELEASE_IMG_REF} +$YQ w -i $values -- catalog.opmImageArgs "--opmImage=${OPM_IMAGE_REF}" + charttmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t charttmpdir) charttmpdir=${charttmpdir}/chart diff --git a/util/image-canonical-ref/main.go b/util/image-canonical-ref/main.go new file mode 100644 index 0000000000..9639d50a11 --- /dev/null +++ b/util/image-canonical-ref/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "context" + "fmt" + "os" + + "github.com/containers/image/v5/docker" + "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/types" +) + +// This is a simple tool to resolve canonical reference of the image. +// E.g. this resolves quay.io/operator-framework/olm:v0.28.0 to +// quay.io/operator-framework/olm@sha256:40d0363f4aa684319cd721c2fcf3321785380fdc74de8ef821317cd25a10782a +func main() { + ctx := context.Background() + + if len(os.Args) != 2 { + fmt.Fprintf(os.Stderr, "usage: %s \n", os.Args[0]) + os.Exit(1) + } + + ref := os.Args[1] + + if err := run(ctx, ref); err != nil { + fmt.Fprintf(os.Stderr, "error running the tool: %s\n", err) + os.Exit(1) + } +} + +func run(ctx context.Context, ref string) error { + imgRef, err := reference.ParseNamed(ref) + if err != nil { + return fmt.Errorf("error parsing image reference %q: %w", ref, err) + } + + sysCtx := &types.SystemContext{} + canonicalRef, err := resolveCanonicalRef(ctx, imgRef, sysCtx) + if err != nil { + return fmt.Errorf("error resolving canonical reference: %w", err) + } + + fmt.Println(canonicalRef.String()) + return nil +} + +func resolveCanonicalRef(ctx context.Context, imgRef reference.Named, sysCtx *types.SystemContext) (reference.Canonical, error) { + if canonicalRef, ok := imgRef.(reference.Canonical); ok { + return canonicalRef, nil + } + + srcRef, err := docker.NewReference(imgRef) + if err != nil { + return nil, fmt.Errorf("error creating reference: %w", err) + } + + imgSrc, err := srcRef.NewImageSource(ctx, sysCtx) + if err != nil { + return nil, fmt.Errorf("error creating image source: %w", err) + } + defer imgSrc.Close() + + imgManifestData, _, err := imgSrc.GetManifest(ctx, nil) + if err != nil { + return nil, fmt.Errorf("error getting manifest: %w", err) + } + imgDigest, err := manifest.Digest(imgManifestData) + if err != nil { + return nil, fmt.Errorf("error getting digest of manifest: %w", err) + } + canonicalRef, err := reference.WithDigest(reference.TrimNamed(imgRef), imgDigest) + if err != nil { + return nil, fmt.Errorf("error creating canonical reference: %w", err) + } + return canonicalRef, nil +}