From 027ea030fa924e12988b7eaaaee878aa671fb127 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 18:13:09 +0200 Subject: [PATCH] Qualify a short base image name before buildah reads it (issue 1824) --- .../cmd/mesh-build-image/build.go | 19 +++++++++- .../cmd/mesh-build-image/qualify_test.go | 35 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 modules/mesh-build-image/cmd/mesh-build-image/qualify_test.go diff --git a/modules/mesh-build-image/cmd/mesh-build-image/build.go b/modules/mesh-build-image/cmd/mesh-build-image/build.go index 2e149852..baee275e 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/build.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/build.go @@ -74,6 +74,23 @@ func unsupportedImage(manifest catalogue.Manifest, a catalogue.Artifact) string return "" } +// qualifyImage names a base image in full, as the controller's parseReference reads it: a name without a registry host +// is the public hub's (docker.io), a single name under `library/`. buildah, with this machine's registry configuration, +// has no unqualified-search registry and refuses a short name (issue 1824); a name that has a host is kept. +func qualifyImage(ref string) string { + name := ref + if at := strings.Index(name, "@"); at >= 0 { + name = name[:at] + } + if slash := strings.Index(name, "/"); slash >= 0 && (strings.ContainsAny(name[:slash], ".:") || name[:slash] == "localhost") { + return ref + } + if !strings.Contains(name, "/") { + return "docker.io/library/" + ref + } + return "docker.io/" + ref +} + // imageArgs are the --build-arg words of the images the manifest pins in build.on, in its order. func imageArgs(manifest catalogue.Manifest) []string { var out []string @@ -82,7 +99,7 @@ func imageArgs(manifest catalogue.Manifest) []string { } for _, on := range manifest.Build.On { if on.Image != "" && on.Arg != "" { - out = append(out, "--build-arg", on.Arg+"="+on.Image) + out = append(out, "--build-arg", on.Arg+"="+qualifyImage(on.Image)) } } return out diff --git a/modules/mesh-build-image/cmd/mesh-build-image/qualify_test.go b/modules/mesh-build-image/cmd/mesh-build-image/qualify_test.go new file mode 100644 index 00000000..4f78cc6c --- /dev/null +++ b/modules/mesh-build-image/cmd/mesh-build-image/qualify_test.go @@ -0,0 +1,35 @@ +package main + +import ( + "slices" + "testing" + + "git.novox.be/novox/mesh-sdk/go/catalogue" +) + +const pin = "@sha256:e4bf19f15fd3218814a4e3c9e0064e1334bd8aa20d5984b9f1a0afd084f8cc00" + +// 1824: a short base image name is qualified the way the controller's parseReference does (the public hub, `library/` +// for a single name), because buildah has no unqualified-search registry here; a qualified name is left as it is. +func TestAShortBaseImageNameIsQualifiedAsTheHubsAndAQualifiedOneIsKept(t *testing.T) { + for in, want := range map[string]string{ + "nats" + pin: "docker.io/library/nats" + pin, + "nats:2.11.17-alpine" + pin: "docker.io/library/nats:2.11.17-alpine" + pin, + "n8nio/n8n" + pin: "docker.io/n8nio/n8n" + pin, + "docker.io/library/alpine" + pin: "docker.io/library/alpine" + pin, + "ghcr.io/org/app:1" + pin: "ghcr.io/org/app:1" + pin, + "localhost:5000/x/y" + pin: "localhost:5000/x/y" + pin, + "registry-1.docker.io/library/a": "registry-1.docker.io/library/a", + } { + if got := qualifyImage(in); got != want { + t.Errorf("%s = %s, want %s", in, got, want) + } + } +} + +func TestTheBuildArgsCarryTheQualifiedName(t *testing.T) { + m := catalogue.Manifest{Build: &catalogue.Build{On: []catalogue.BuildsOn{{Arg: "NATS_BASE", Image: "nats" + pin}}}} + if got, want := imageArgs(m), []string{"--build-arg", "NATS_BASE=docker.io/library/nats" + pin}; !slices.Equal(got, want) { + t.Errorf("%v, want %v", got, want) + } +}