Skip to content

Commit

Permalink
Fix canonical image ref resolution (#3434)
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
m1kola authored Nov 11, 2024
1 parent da0f7da commit 9ec1b02
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 14 deletions.
15 changes: 1 addition & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -306,37 +306,24 @@ 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)
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)
./scripts/package_quickstart.sh deploy/$(TARGET)/manifests/$(RELEASE_VERSION) deploy/$(TARGET)/quickstart/olm.yaml deploy/$(TARGET)/quickstart/crds.yaml deploy/$(TARGET)/quickstart/install.sh
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
Expand Down
15 changes: 15 additions & 0 deletions scripts/package_release.sh
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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
Expand Down
78 changes: 78 additions & 0 deletions util/image-canonical-ref/main.go
Original file line number Diff line number Diff line change
@@ -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 <image reference>\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
}

0 comments on commit 9ec1b02

Please sign in to comment.