Skip to content

Commit

Permalink
show name for images
Browse files Browse the repository at this point in the history
Signed-off-by: Ye Sijun <junnplus@gmail.com>
  • Loading branch information
junnplus committed Jun 27, 2022
1 parent b3caee1 commit 5fb91ca
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 41 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,7 @@ Flags:
- :nerd_face: `--format=wide`: Wide table
- :nerd_face: `--format=json`: Alias of `--format='{{json .}}'`
- :whale: `--digests`: Show digests (compatible with Docker, unlike ID)
- :nerd_face: `--names`: Show image names

Unimplemented `docker images` flags: `--filter`

Expand Down
102 changes: 61 additions & 41 deletions cmd/nerdctl/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Properties:
return []string{"json", "table", "wide"}, cobra.ShellCompDirectiveNoFileComp
})
imagesCommand.Flags().Bool("digests", false, "Show digests (compatible with Docker, unlike ID)")
imagesCommand.Flags().Bool("names", false, "Show image names")
imagesCommand.Flags().BoolP("all", "a", true, "(unimplemented yet, always true)")

return imagesCommand
Expand All @@ -90,6 +91,7 @@ func imagesAction(cmd *cobra.Command, args []string) error {
return err
}
filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String()))
filters = append(filters, fmt.Sprintf("name==%s", args[0]))
}
client, ctx, cancel, err := newClient(cmd)
if err != nil {
Expand Down Expand Up @@ -119,6 +121,7 @@ type imagePrintable struct {
ID string // image target digest (not config digest, unlike Docker), or its short form
Repository string
Tag string // "<none>" or tag
Name string // image name
Size string // the size of the unpacked snapshots.
BlobSize string // the size of the blobs in the content store (nerdctl extension)
// TODO: "SharedSize", "UniqueSize", "VirtualSize"
Expand All @@ -138,6 +141,10 @@ func printImages(ctx context.Context, cmd *cobra.Command, client *containerd.Cli
if err != nil {
return err
}
namesFlag, err := cmd.Flags().GetBool("names")
if err != nil {
return err
}
var w io.Writer
w = os.Stdout
format, err := cmd.Flags().GetString("format")
Expand All @@ -152,11 +159,17 @@ func printImages(ctx context.Context, cmd *cobra.Command, client *containerd.Cli
case "", "table", "wide":
w = tabwriter.NewWriter(w, 4, 8, 4, ' ', 0)
if !quiet {
if digestsFlag {
fmt.Fprintln(w, "REPOSITORY\tTAG\tDIGEST\tIMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE")
printHeader := ""
if namesFlag {
printHeader += "NAME\t"
} else {
fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE")
printHeader += "REPOSITORY\tTAG\t"
}
if digestsFlag {
printHeader += "DIGEST\t"
}
printHeader += "IMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE"
fmt.Fprintln(w, printHeader)
}
case "raw":
return errors.New("unsupported format: \"raw\"")
Expand All @@ -181,6 +194,7 @@ func printImages(ctx context.Context, cmd *cobra.Command, client *containerd.Cli
quiet: quiet,
noTrunc: noTrunc,
digestsFlag: digestsFlag,
namesFlag: namesFlag,
tmpl: tmpl,
client: client,
contentStore: client.ContentStore(),
Expand All @@ -199,12 +213,12 @@ func printImages(ctx context.Context, cmd *cobra.Command, client *containerd.Cli
}

type imagePrinter struct {
w io.Writer
quiet, noTrunc, digestsFlag bool
tmpl *template.Template
client *containerd.Client
contentStore content.Store
snapshotter snapshots.Snapshotter
w io.Writer
quiet, noTrunc, digestsFlag, namesFlag bool
tmpl *template.Template
client *containerd.Client
contentStore content.Store
snapshotter snapshots.Snapshotter
}

func (x *imagePrinter) printImage(ctx context.Context, img images.Image) error {
Expand All @@ -228,29 +242,44 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images.
return nil
}

blobSize, err := img.Size(ctx, x.contentStore, platMC)
image := containerd.NewImageWithPlatform(x.client, img, platMC)
desc, err := image.Config(ctx)
if err != nil {
logrus.WithError(err).Warnf("failed to get config of image %q for platform %q", img.Name, platforms.Format(ociPlatform))
}
var (
repository string
tag string
)
if x.namesFlag || desc.Digest.String() != img.Name {
repository, tag = imgutil.ParseRepoTag(img.Name)
}

blobSize, err := image.Size(ctx)
if err != nil {
logrus.WithError(err).Warnf("failed to get blob size of image %q for platform %q", img.Name, platforms.Format(ociPlatform))
}

size, err := unpackedImageSize(ctx, x.client, x.snapshotter, img, platMC)
size, err := unpackedImageSize(ctx, x.snapshotter, image)
if err != nil {
logrus.WithError(err).Warnf("failed to get unpacked size of image %q for platform %q", img.Name, platforms.Format(ociPlatform))
}

repository, tag := imgutil.ParseRepoTag(img.Name)

p := imagePrintable{
CreatedAt: img.CreatedAt.Round(time.Second).Local().String(), // format like "2021-08-07 02:19:45 +0900 JST"
CreatedSince: formatter.TimeSinceInHuman(img.CreatedAt),
Digest: img.Target.Digest.String(),
ID: img.Target.Digest.String(),
Repository: repository,
Tag: tag,
Name: img.Name,
Size: progress.Bytes(size).String(),
BlobSize: progress.Bytes(blobSize).String(),
Platform: platforms.Format(ociPlatform),
}
if p.Repository == "" {
p.Repository = "<none>"
}
if p.Tag == "" {
p.Tag = "<none>" // for Docker compatibility
}
Expand All @@ -271,31 +300,24 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images.
return err
}
} else {
if x.digestsFlag {
if _, err := fmt.Fprintf(x.w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
p.Repository,
p.Tag,
p.Digest,
p.ID,
p.CreatedSince,
p.Platform,
p.Size,
p.BlobSize,
); err != nil {
return err
}
format := ""
args := []interface{}{}
if x.namesFlag {
format += "%s\t"
args = append(args, p.Name)
} else {
if _, err := fmt.Fprintf(x.w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
p.Repository,
p.Tag,
p.ID,
p.CreatedSince,
p.Platform,
p.Size,
p.BlobSize,
); err != nil {
return err
}
format += "%s\t%s\t"
args = append(args, p.Repository, p.Tag)
}
if x.digestsFlag {
format += "%s\t"
args = append(args, p.Digest)
}

format += "%s\t%s\t%s\t%s\t%s\n"
args = append(args, p.ID, p.CreatedSince, p.Platform, p.Size, p.BlobSize)
if _, err := fmt.Fprintf(x.w, format, args...); err != nil {
return err
}
}
return nil
Expand Down Expand Up @@ -335,9 +357,7 @@ func (key snapshotKey) add(ctx context.Context, s snapshots.Snapshotter, usage *

// unpackedImageSize is the size of the unpacked snapshots.
// Does not contain the size of the blobs in the content store. (Corresponds to Docker).
func unpackedImageSize(ctx context.Context, client *containerd.Client, s snapshots.Snapshotter, i images.Image, platMC platforms.MatchComparer) (int64, error) {
img := containerd.NewImageWithPlatform(client, i, platMC)

func unpackedImageSize(ctx context.Context, s snapshots.Snapshotter, img containerd.Image) (int64, error) {
diffIDs, err := img.RootFS(ctx)
if err != nil {
return 0, err
Expand All @@ -347,7 +367,7 @@ func unpackedImageSize(ctx context.Context, client *containerd.Client, s snapsho
usage, err := s.Usage(ctx, chainID)
if err != nil {
if errdefs.IsNotFound(err) {
logrus.WithError(err).Debugf("image %q seems not unpacked", i.Name)
logrus.WithError(err).Debugf("image %q seems not unpacked", img.Name())
return 0, nil
}
return 0, err
Expand Down
1 change: 1 addition & 0 deletions pkg/idutil/imagewalker/imagewalker.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func (w *ImageWalker) Walk(ctx context.Context, req string) (int, error) {
filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String()))
}
filters = append(filters,
fmt.Sprintf("name==%s", req),
fmt.Sprintf("target.digest~=^sha256:%s.*$", regexp.QuoteMeta(req)),
fmt.Sprintf("target.digest~=^%s.*$", regexp.QuoteMeta(req)),
)
Expand Down

0 comments on commit 5fb91ca

Please sign in to comment.