show platforms for `docker manifest ls`

Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
This commit is contained in:
Wayne Cheng 2024-01-06 11:24:51 +08:00
parent 46b474267b
commit b039c0e9af
4 changed files with 45 additions and 17 deletions

View File

@ -1,16 +1,21 @@
package manifest
import (
"fmt"
"strings"
"github.com/distribution/reference"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/cli/manifest/types"
)
const (
defaultManifestListQuietFormat = "{{.Name}}"
defaultManifestListTableFormat = "table {{.Repository}}\t{{.Tag}}"
defaultManifestListTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.Platforms}}"
repositoryHeader = "REPOSITORY"
tagHeader = "TAG"
platformsHeader = "PLATFORMS"
)
// NewFormat returns a Format for rendering using a manifest list Context
@ -31,15 +36,16 @@ func NewFormat(source string, quiet bool) formatter.Format {
}
// FormatWrite writes formatted manifestLists using the Context
func FormatWrite(ctx formatter.Context, manifestLists []reference.Reference) error {
func FormatWrite(ctx formatter.Context, manifestLists []reference.Reference, manifests map[string][]types.ImageManifest) error {
render := func(format func(subContext formatter.SubContext) error) error {
for _, manifestList := range manifestLists {
if n, ok := manifestList.(reference.Named); ok {
if nt, ok := n.(reference.NamedTagged); ok {
if err := format(&manifestListContext{
name: reference.FamiliarString(manifestList),
repo: reference.FamiliarName(nt),
tag: nt.Tag(),
name: reference.FamiliarString(manifestList),
repo: reference.FamiliarName(nt),
tag: nt.Tag(),
imageManifests: manifests[manifestList.String()],
}); err != nil {
return err
}
@ -53,9 +59,10 @@ func FormatWrite(ctx formatter.Context, manifestLists []reference.Reference) err
type manifestListContext struct {
formatter.HeaderContext
name string
repo string
tag string
name string
repo string
tag string
imageManifests []types.ImageManifest
}
func newManifestListContext() *manifestListContext {
@ -64,6 +71,7 @@ func newManifestListContext() *manifestListContext {
"Name": formatter.NameHeader,
"Repository": repositoryHeader,
"Tag": tagHeader,
"Platforms": platformsHeader,
}
return &manifestListCtx
}
@ -83,3 +91,13 @@ func (c *manifestListContext) Repository() string {
func (c *manifestListContext) Tag() string {
return c.tag
}
func (c *manifestListContext) Platforms() string {
platforms := []string{}
for _, manifest := range c.imageManifests {
os := manifest.Descriptor.Platform.OS
arch := manifest.Descriptor.Platform.Architecture
platforms = append(platforms, fmt.Sprintf("%s/%s", os, arch))
}
return strings.Join(platforms, ", ")
}

View File

@ -8,8 +8,8 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
flagsHelper "github.com/docker/cli/cli/flags"
"github.com/docker/cli/cli/manifest/types"
"github.com/fvbommel/sortorder"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -42,9 +42,16 @@ func runList(dockerCli command.Cli, options listOptions) error {
var manifestLists []reference.Reference
manifestLists, searchErr := manifestStore.List()
if searchErr != nil {
return errors.New(searchErr.Error())
manifestLists, err := manifestStore.List()
if err != nil {
return err
}
manifests := map[string][]types.ImageManifest{}
for _, manifestList := range manifestLists {
if imageManifests, err := manifestStore.GetList(manifestList); err == nil {
manifests[manifestList.String()] = imageManifests
}
}
format := options.format
@ -63,5 +70,5 @@ func runList(dockerCli command.Cli, options listOptions) error {
sort.Slice(manifestLists, func(i, j int) bool {
return sortorder.NaturalLess(manifestLists[i].String(), manifestLists[j].String())
})
return FormatWrite(manifestListsCtx, manifestLists)
return FormatWrite(manifestListsCtx, manifestLists, manifests)
}

View File

@ -58,7 +58,10 @@ func TestList(t *testing.T) {
err := manifestStore.Save(list1, namedRef, fullImageManifest(t, namedRef))
assert.NilError(t, err)
namedRef = ref(t, "alpine:3.1")
err = manifestStore.Save(list1, namedRef, fullImageManifest(t, namedRef))
imageManifest := fullImageManifest(t, namedRef)
imageManifest.Descriptor.Platform.OS = "linux"
imageManifest.Descriptor.Platform.Architecture = "arm64"
err = manifestStore.Save(list1, namedRef, imageManifest)
assert.NilError(t, err)
list2 := ref(t, "second:2")

View File

@ -1,3 +1,3 @@
REPOSITORY TAG
example.com/first 1
example.com/second 2
REPOSITORY TAG PLATFORMS
example.com/first 1 linux/amd64, linux/arm64
example.com/second 2 linux/amd64