Skip to content

Commit 9a77249

Browse files
author
Mikalai Radchuk
committed
Fix canonical image ref resolution
Adds a new util to reliably resolve canonical reference to the image. 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]>
1 parent 2dd27bd commit 9a77249

File tree

3 files changed

+84
-11
lines changed

3 files changed

+84
-11
lines changed

Makefile

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -306,23 +306,19 @@ verify: vendor verify-codegen verify-mockgen verify-manifests #HELP Run all veri
306306

307307
#SECTION Release
308308

309-
.PHONY: pull-opm
310-
pull-opm:
311-
docker pull $(OPERATOR_REGISTRY_IMAGE)
312-
313309
.PHONY: package
314310
package: $(YQ) $(HELM) #HELP Package OLM for release
315-
package: OLM_RELEASE_IMG_REF=$(shell docker inspect --format='{{index .RepoDigests 0}}' $(IMAGE_REPO):$(RELEASE_VERSION))
316-
package: OPM_IMAGE_REF=$(shell docker inspect --format='{{index .RepoDigests 0}}' $(OPERATOR_REGISTRY_IMAGE))
311+
package: OLM_RELEASE_IMG_REF=$(shell go run util/image-canonical-ref/main.go $(IMAGE_REPO):$(RELEASE_VERSION))
312+
package: OPM_IMAGE_REF=$(shell go run util/image-canonical-ref/main.go $(OPERATOR_REGISTRY_IMAGE))
317313
package:
318314
ifndef TARGET
319315
$(error TARGET is undefined)
320316
endif
321317
ifndef RELEASE_VERSION
322318
$(error RELEASE_VERSION is undefined)
323319
endif
324-
@echo "Getting operator registry image"
325-
docker pull $(OPERATOR_REGISTRY_IMAGE)
320+
@echo "Using OPM image $(OPM_IMAGE_REF)"
321+
@echo "Using OLM image $(OLM_RELEASE_IMG_REF)"
326322
$(YQ) w -i deploy/$(TARGET)/values.yaml olm.image.ref $(OLM_RELEASE_IMG_REF)
327323
$(YQ) w -i deploy/$(TARGET)/values.yaml catalog.image.ref $(OLM_RELEASE_IMG_REF)
328324
$(YQ) w -i deploy/$(TARGET)/values.yaml package.image.ref $(OLM_RELEASE_IMG_REF)
@@ -334,9 +330,8 @@ ifeq ($(PACKAGE_QUICKSTART), true)
334330
endif
335331

336332
.PHONY: release
337-
release: pull-opm manifests # pull the opm image to get the digest
333+
release: manifests
338334
@echo "Generating the $(RELEASE_VERSION) release"
339-
docker pull $(IMAGE_REPO):$(RELEASE_VERSION)
340335
$(MAKE) TARGET=upstream RELEASE_VERSION=$(RELEASE_VERSION) PACKAGE_QUICKSTART=true package
341336

342337
.PHONY: FORCE

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.22.5
44

55
require (
66
github.com/blang/semver/v4 v4.0.0
7+
github.com/containers/image/v5 v5.32.2
78
github.com/coreos/go-semver v0.3.1
89
github.com/distribution/reference v0.6.0
910
github.com/evanphx/json-patch v5.9.0+incompatible
@@ -73,7 +74,6 @@ require (
7374
github.com/containerd/ttrpc v1.2.5 // indirect
7475
github.com/containerd/typeurl/v2 v2.1.1 // indirect
7576
github.com/containers/common v0.60.4 // indirect
76-
github.com/containers/image/v5 v5.32.2 // indirect
7777
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
7878
github.com/containers/ocicrypt v1.2.0 // indirect
7979
github.com/containers/storage v1.55.0 // indirect

util/image-canonical-ref/main.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/containers/image/v5/docker"
9+
"github.com/containers/image/v5/docker/reference"
10+
"github.com/containers/image/v5/manifest"
11+
"github.com/containers/image/v5/types"
12+
)
13+
14+
// This is a simple tool to resolve canonical reference of the image.
15+
// E.g. this resolves quay.io/operator-framework/olm:v0.28.0 to
16+
// quay.io/operator-framework/olm@sha256:40d0363f4aa684319cd721c2fcf3321785380fdc74de8ef821317cd25a10782a
17+
func main() {
18+
ctx := context.Background()
19+
20+
if len(os.Args) != 2 {
21+
fmt.Fprintf(os.Stderr, "usage: %s <image reference>\n", os.Args[0])
22+
os.Exit(1)
23+
}
24+
25+
ref := os.Args[1]
26+
27+
if err := run(ctx, ref); err != nil {
28+
fmt.Fprintf(os.Stderr, "error running the tool: %s\n", err)
29+
os.Exit(1)
30+
}
31+
}
32+
33+
func run(ctx context.Context, ref string) error {
34+
imgRef, err := reference.ParseNamed(ref)
35+
if err != nil {
36+
return fmt.Errorf("error parsing image reference %q: %w", ref, err)
37+
}
38+
39+
sysCtx := &types.SystemContext{}
40+
canonicalRef, err := resolveCanonicalRef(ctx, imgRef, sysCtx)
41+
if err != nil {
42+
return fmt.Errorf("error resolving canonical reference: %w", err)
43+
}
44+
45+
fmt.Println(canonicalRef.String())
46+
return nil
47+
}
48+
49+
func resolveCanonicalRef(ctx context.Context, imgRef reference.Named, sysCtx *types.SystemContext) (reference.Canonical, error) {
50+
if canonicalRef, ok := imgRef.(reference.Canonical); ok {
51+
return canonicalRef, nil
52+
}
53+
54+
srcRef, err := docker.NewReference(imgRef)
55+
if err != nil {
56+
return nil, fmt.Errorf("error creating reference: %w", err)
57+
}
58+
59+
imgSrc, err := srcRef.NewImageSource(ctx, sysCtx)
60+
if err != nil {
61+
return nil, fmt.Errorf("error creating image source: %w", err)
62+
}
63+
defer imgSrc.Close()
64+
65+
imgManifestData, _, err := imgSrc.GetManifest(ctx, nil)
66+
if err != nil {
67+
return nil, fmt.Errorf("error getting manifest: %w", err)
68+
}
69+
imgDigest, err := manifest.Digest(imgManifestData)
70+
if err != nil {
71+
return nil, fmt.Errorf("error getting digest of manifest: %w", err)
72+
}
73+
canonicalRef, err := reference.WithDigest(reference.TrimNamed(imgRef), imgDigest)
74+
if err != nil {
75+
return nil, fmt.Errorf("error creating canonical reference: %w", err)
76+
}
77+
return canonicalRef, nil
78+
}

0 commit comments

Comments
 (0)