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 c10a98b0d8f4..49d359d8c028 100644 --- a/cli/command/manifest/util.go +++ b/cli/command/manifest/util.go @@ -9,53 +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: "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 { 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