From d35139c89fb5f5b78e86bde591388f5552a250fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Fri, 30 Oct 2026 15:19:56 +0800 Subject: [PATCH 1/2] manifest: add loong64 to manifest annotate bash completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 吴小白 <296015668@qq.com> Signed-off-by: Sebastiaan van Stijn --- cli/command/manifest/util.go | 1 + contrib/completion/bash/docker | 1 + 2 files changed, 2 insertions(+) diff --git a/cli/command/manifest/util.go b/cli/command/manifest/util.go index c10a98b0d8f4..7f84aedd1516 100644 --- a/cli/command/manifest/util.go +++ b/cli/command/manifest/util.go @@ -32,6 +32,7 @@ var validOSArches = map[osArch]bool{ {os: "linux", arch: "amd64"}: true, {os: "linux", arch: "arm"}: true, {os: "linux", arch: "arm64"}: true, + {os: "linux", arch: "loong64"}: true, {os: "linux", arch: "ppc64le"}: true, {os: "linux", arch: "mips64"}: true, {os: "linux", arch: "mips64le"}: true, diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index a78b08a6e473..b9b7a28ec263 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -4156,6 +4156,7 @@ _docker_manifest_annotate() { amd64 arm arm64 + loong64 mips64 mips64le ppc64le From bf8066ca1839d5fd3d8971410c41b822b2653056 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 30 Oct 2026 11:17:48 +0100 Subject: [PATCH 2/2] manifest: remove hard-coded os/arch list in validation Replace the hardcoded list of supported OS/architecture combinations with syntax validation using containerd/platforms. This allows annotating manifests with platforms that are not explicitly known to the CLI, while still rejecting missing or malformed values. The validation uses a FormatAll/Parse roundtrip until containerd/platforms provides a dedicated validation function. Signed-off-by: Sebastiaan van Stijn --- cli/command/manifest/annotate.go | 12 +++++-- cli/command/manifest/annotate_test.go | 15 +++++---- cli/command/manifest/util.go | 48 --------------------------- 3 files changed, 18 insertions(+), 57 deletions(-) diff --git a/cli/command/manifest/annotate.go b/cli/command/manifest/annotate.go index a9507deb73f0..fd8102bfc088 100644 --- a/cli/command/manifest/annotate.go +++ b/cli/command/manifest/annotate.go @@ -10,6 +10,7 @@ import ( "slices" "github.com/containerd/errdefs" + "github.com/containerd/platforms" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config" @@ -139,8 +140,15 @@ func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error { imageManifest.Descriptor.Platform.OSVersion = opts.osVersion } - if !isValidOSArch(imageManifest.Descriptor.Platform.OS, imageManifest.Descriptor.Platform.Architecture) { - return fmt.Errorf("manifest entry for image has unsupported os/arch combination: %s/%s", opts.os, opts.arch) + // Validate platform syntax, without restricting OS/architecture combinations. + // + // TODO(thaJeztah): Implement a platforms.Validate in containerd/platforms and replace this code. + p := imageManifest.Descriptor.Platform + if p.OS == "" || p.Architecture == "" { + return fmt.Errorf("manifest entry for image has missing os/architecture: %q/%q", p.OS, p.Architecture) + } + if _, err := platforms.Parse(platforms.FormatAll(*p)); err != nil { + return fmt.Errorf("manifest entry for image has invalid platform: %w", err) } return manifestStore.Save(targetRef, imgRef, imageManifest) } diff --git a/cli/command/manifest/annotate_test.go b/cli/command/manifest/annotate_test.go index f2c924e45ffc..d50c54c83c78 100644 --- a/cli/command/manifest/annotate_test.go +++ b/cli/command/manifest/annotate_test.go @@ -58,15 +58,16 @@ func TestManifestAnnotate(t *testing.T) { assert.ErrorContains(t, cmd.Execute(), expectedError) cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"}) - cmd.Flags().Set("os", "freebsd") - cmd.Flags().Set("arch", "fake") - cmd.Flags().Set("os-version", "1") - cmd.Flags().Set("os-features", "feature1") - cmd.Flags().Set("variant", "v7") - expectedError = "manifest entry for image has unsupported os/arch combination" + assert.NilError(t, cmd.Flags().Set("os", "freebsd")) + assert.NilError(t, cmd.Flags().Set("arch", "")) + assert.NilError(t, cmd.Flags().Set("os-version", "1")) + assert.NilError(t, cmd.Flags().Set("os-features", "feature1")) + assert.NilError(t, cmd.Flags().Set("variant", "v7")) + + expectedError = "manifest entry for image has invalid platform" assert.ErrorContains(t, cmd.Execute(), expectedError) - cmd.Flags().Set("arch", "arm") + assert.NilError(t, cmd.Flags().Set("arch", "arm")) assert.NilError(t, cmd.Execute()) cmd = newInspectCommand(cli) diff --git a/cli/command/manifest/util.go b/cli/command/manifest/util.go index 7f84aedd1516..49d359d8c028 100644 --- a/cli/command/manifest/util.go +++ b/cli/command/manifest/util.go @@ -9,54 +9,6 @@ import ( "github.com/docker/cli/cli/manifest/types" ) -type osArch struct { - os string - arch string -} - -// Remove any unsupported os/arch combo -// list of valid os/arch values (see "Optional Environment Variables" section -// of https://go.dev/doc/install/source -// Added linux/s390x as we know System z support already exists -// Keep in sync with _docker_manifest_annotate in contrib/completion/bash/docker -var validOSArches = map[osArch]bool{ - {os: "darwin", arch: "386"}: true, - {os: "darwin", arch: "amd64"}: true, - {os: "darwin", arch: "arm"}: true, - {os: "darwin", arch: "arm64"}: true, - {os: "dragonfly", arch: "amd64"}: true, - {os: "freebsd", arch: "386"}: true, - {os: "freebsd", arch: "amd64"}: true, - {os: "freebsd", arch: "arm"}: true, - {os: "linux", arch: "386"}: true, - {os: "linux", arch: "amd64"}: true, - {os: "linux", arch: "arm"}: true, - {os: "linux", arch: "arm64"}: true, - {os: "linux", arch: "loong64"}: true, - {os: "linux", arch: "ppc64le"}: true, - {os: "linux", arch: "mips64"}: true, - {os: "linux", arch: "mips64le"}: true, - {os: "linux", arch: "riscv64"}: true, - {os: "linux", arch: "s390x"}: true, - {os: "netbsd", arch: "386"}: true, - {os: "netbsd", arch: "amd64"}: true, - {os: "netbsd", arch: "arm"}: true, - {os: "openbsd", arch: "386"}: true, - {os: "openbsd", arch: "amd64"}: true, - {os: "openbsd", arch: "arm"}: true, - {os: "plan9", arch: "386"}: true, - {os: "plan9", arch: "amd64"}: true, - {os: "solaris", arch: "amd64"}: true, - {os: "windows", arch: "386"}: true, - {os: "windows", arch: "amd64"}: true, -} - -func isValidOSArch(os string, arch string) bool { - // check for existence of this combo - _, ok := validOSArches[osArch{os, arch}] - return ok -} - func normalizeReference(ref string) (reference.Named, error) { namedRef, err := reference.ParseNormalizedNamed(ref) if err != nil {