From 65a0034c67dbcc9e7a2baf285fca7d2435b689a3 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Sun, 5 Jun 2016 20:55:47 -0700 Subject: [PATCH] Use spf13/cobra for docker images This fix is part of the effort to convert commands to spf13/cobra #23211. Thif fix coverted command `docker images` to use spf13/cobra NOTE: As part of this fix, a new function `RequiresMaxArgs()` has been defined in `cli/required.go`. This func returns an error if there is not at most max args Signed-off-by: Yong Tang --- api/client/commands.go | 1 - api/client/image/images.go | 103 ++++++++++++++++++++++++++++++++++++ api/client/images.go | 81 ---------------------------- cli/cobraadaptor/adaptor.go | 1 + cli/required.go | 17 ++++++ cli/usage.go | 1 - 6 files changed, 121 insertions(+), 83 deletions(-) create mode 100644 api/client/image/images.go delete mode 100644 api/client/images.go diff --git a/api/client/commands.go b/api/client/commands.go index fcd5a311bb..6d6728e2a6 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -8,7 +8,6 @@ func (cli *DockerCli) Command(name string) func(...string) error { "cp": cli.CmdCp, "events": cli.CmdEvents, "exec": cli.CmdExec, - "images": cli.CmdImages, "info": cli.CmdInfo, "inspect": cli.CmdInspect, "load": cli.CmdLoad, diff --git a/api/client/image/images.go b/api/client/image/images.go new file mode 100644 index 0000000000..460fb79801 --- /dev/null +++ b/api/client/image/images.go @@ -0,0 +1,103 @@ +package image + +import ( + "golang.org/x/net/context" + + "github.com/docker/docker/api/client" + "github.com/docker/docker/api/client/formatter" + "github.com/docker/docker/cli" + "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/filters" + "github.com/spf13/cobra" +) + +type imagesOptions struct { + matchName string + + quiet bool + all bool + noTrunc bool + showDigests bool + format string + filter []string +} + +// NewImagesCommand create a new `docker images` command +func NewImagesCommand(dockerCli *client.DockerCli) *cobra.Command { + var opts imagesOptions + + cmd := &cobra.Command{ + Use: "images [OPTIONS] [REPOSITORY[:TAG]]", + Short: "List images", + Args: cli.RequiresMaxArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) > 0 { + opts.matchName = args[0] + } + return runImages(dockerCli, opts) + }, + } + + flags := cmd.Flags() + + flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only show numeric IDs") + flags.BoolVarP(&opts.all, "all", "a", false, "Show all images (default hides intermediate images)") + flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output") + flags.BoolVar(&opts.showDigests, "digests", false, "Show digests") + flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template") + flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Filter output based on conditions provided") + + return cmd +} + +func runImages(dockerCli *client.DockerCli, opts imagesOptions) error { + ctx := context.Background() + + // Consolidate all filter flags, and sanity check them early. + // They'll get process in the daemon/server. + imageFilterArgs := filters.NewArgs() + for _, f := range opts.filter { + var err error + imageFilterArgs, err = filters.ParseFlag(f, imageFilterArgs) + if err != nil { + return err + } + } + + matchName := opts.matchName + + options := types.ImageListOptions{ + MatchName: matchName, + All: opts.all, + Filters: imageFilterArgs, + } + + images, err := dockerCli.Client().ImageList(ctx, options) + if err != nil { + return err + } + + f := opts.format + if len(f) == 0 { + if len(dockerCli.ImagesFormat()) > 0 && !opts.quiet { + f = dockerCli.ImagesFormat() + } else { + f = "table" + } + } + + imagesCtx := formatter.ImageContext{ + Context: formatter.Context{ + Output: dockerCli.Out(), + Format: f, + Quiet: opts.quiet, + Trunc: !opts.noTrunc, + }, + Digest: opts.showDigests, + Images: images, + } + + imagesCtx.Write() + + return nil +} diff --git a/api/client/images.go b/api/client/images.go deleted file mode 100644 index 4840b63def..0000000000 --- a/api/client/images.go +++ /dev/null @@ -1,81 +0,0 @@ -package client - -import ( - "golang.org/x/net/context" - - "github.com/docker/docker/api/client/formatter" - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/filters" -) - -// CmdImages lists the images in a specified repository, or all top-level images if no repository is specified. -// -// Usage: docker images [OPTIONS] [REPOSITORY] -func (cli *DockerCli) CmdImages(args ...string) error { - cmd := Cli.Subcmd("images", []string{"[REPOSITORY[:TAG]]"}, Cli.DockerCommands["images"].Description, true) - quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") - all := cmd.Bool([]string{"a", "-all"}, false, "Show all images (default hides intermediate images)") - noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Don't truncate output") - showDigests := cmd.Bool([]string{"-digests"}, false, "Show digests") - format := cmd.String([]string{"-format"}, "", "Pretty-print images using a Go template") - - flFilter := opts.NewListOpts(nil) - cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") - cmd.Require(flag.Max, 1) - - cmd.ParseFlags(args, true) - - // Consolidate all filter flags, and sanity check them early. - // They'll get process in the daemon/server. - imageFilterArgs := filters.NewArgs() - for _, f := range flFilter.GetAll() { - var err error - imageFilterArgs, err = filters.ParseFlag(f, imageFilterArgs) - if err != nil { - return err - } - } - - var matchName string - if cmd.NArg() == 1 { - matchName = cmd.Arg(0) - } - - options := types.ImageListOptions{ - MatchName: matchName, - All: *all, - Filters: imageFilterArgs, - } - - images, err := cli.client.ImageList(context.Background(), options) - if err != nil { - return err - } - - f := *format - if len(f) == 0 { - if len(cli.ImagesFormat()) > 0 && !*quiet { - f = cli.ImagesFormat() - } else { - f = "table" - } - } - - imagesCtx := formatter.ImageContext{ - Context: formatter.Context{ - Output: cli.out, - Format: f, - Quiet: *quiet, - Trunc: !*noTrunc, - }, - Digest: *showDigests, - Images: images, - } - - imagesCtx.Write() - - return nil -} diff --git a/cli/cobraadaptor/adaptor.go b/cli/cobraadaptor/adaptor.go index 0d536f0608..4f1f77ca00 100644 --- a/cli/cobraadaptor/adaptor.go +++ b/cli/cobraadaptor/adaptor.go @@ -51,6 +51,7 @@ func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor { container.NewUnpauseCommand(dockerCli), container.NewWaitCommand(dockerCli), image.NewHistoryCommand(dockerCli), + image.NewImagesCommand(dockerCli), image.NewRemoveCommand(dockerCli), image.NewSearchCommand(dockerCli), image.NewImportCommand(dockerCli), diff --git a/cli/required.go b/cli/required.go index 0cf35b3d68..0c08e64f1a 100644 --- a/cli/required.go +++ b/cli/required.go @@ -43,6 +43,23 @@ func RequiresMinArgs(min int) cobra.PositionalArgs { } } +// RequiresMaxArgs returns an error if there is not at most max args +func RequiresMaxArgs(max int) cobra.PositionalArgs { + return func(cmd *cobra.Command, args []string) error { + if len(args) <= max { + return nil + } + return fmt.Errorf( + "\"%s\" requires at most %d argument(s).\nSee '%s --help'.\n\nUsage: %s\n\n%s", + cmd.CommandPath(), + max, + cmd.CommandPath(), + cmd.UseLine(), + cmd.Short, + ) + } +} + // RequiresMinMaxArgs returns an error if there is not at least min args and at most max args func RequiresMinMaxArgs(min int, max int) cobra.PositionalArgs { return func(cmd *cobra.Command, args []string) error { diff --git a/cli/usage.go b/cli/usage.go index baf4948931..a144df1af8 100644 --- a/cli/usage.go +++ b/cli/usage.go @@ -13,7 +13,6 @@ var DockerCommandUsage = []Command{ {"cp", "Copy files/folders between a container and the local filesystem"}, {"events", "Get real time events from the server"}, {"exec", "Run a command in a running container"}, - {"images", "List images"}, {"info", "Display system-wide information"}, {"inspect", "Return low-level information on a container or image"}, {"load", "Load an image from a tar archive or STDIN"},