github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli/command/image/list.go (about) 1 package image 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 8 "github.com/docker/docker/api/types/image" 9 "github.com/khulnasoft/cli/cli" 10 "github.com/khulnasoft/cli/cli/command" 11 "github.com/khulnasoft/cli/cli/command/formatter" 12 flagsHelper "github.com/khulnasoft/cli/cli/flags" 13 "github.com/khulnasoft/cli/opts" 14 "github.com/spf13/cobra" 15 ) 16 17 type imagesOptions struct { 18 matchName string 19 20 quiet bool 21 all bool 22 noTrunc bool 23 showDigests bool 24 format string 25 filter opts.FilterOpt 26 calledAs string 27 } 28 29 // NewImagesCommand creates a new `docker images` command 30 func NewImagesCommand(dockerCLI command.Cli) *cobra.Command { 31 options := imagesOptions{filter: opts.NewFilterOpt()} 32 33 cmd := &cobra.Command{ 34 Use: "images [OPTIONS] [REPOSITORY[:TAG]]", 35 Short: "List images", 36 Args: cli.RequiresMaxArgs(1), 37 RunE: func(cmd *cobra.Command, args []string) error { 38 if len(args) > 0 { 39 options.matchName = args[0] 40 } 41 // Pass through how the command was invoked. We use this to print 42 // warnings when an ambiguous argument was passed when using the 43 // legacy (top-level) "docker images" subcommand. 44 options.calledAs = cmd.CalledAs() 45 return runImages(cmd.Context(), dockerCLI, options) 46 }, 47 Annotations: map[string]string{ 48 "category-top": "7", 49 "aliases": "docker image ls, docker image list, docker images", 50 }, 51 } 52 53 flags := cmd.Flags() 54 55 flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only show image IDs") 56 flags.BoolVarP(&options.all, "all", "a", false, "Show all images (default hides intermediate images)") 57 flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") 58 flags.BoolVar(&options.showDigests, "digests", false, "Show digests") 59 flags.StringVar(&options.format, "format", "", flagsHelper.FormatHelp) 60 flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") 61 62 return cmd 63 } 64 65 func newListCommand(dockerCLI command.Cli) *cobra.Command { 66 cmd := *NewImagesCommand(dockerCLI) 67 cmd.Aliases = []string{"list"} 68 cmd.Use = "ls [OPTIONS] [REPOSITORY[:TAG]]" 69 return &cmd 70 } 71 72 func runImages(ctx context.Context, dockerCLI command.Cli, options imagesOptions) error { 73 filters := options.filter.Value() 74 if options.matchName != "" { 75 filters.Add("reference", options.matchName) 76 } 77 78 images, err := dockerCLI.Client().ImageList(ctx, image.ListOptions{ 79 All: options.all, 80 Filters: filters, 81 }) 82 if err != nil { 83 return err 84 } 85 86 format := options.format 87 if len(format) == 0 { 88 if len(dockerCLI.ConfigFile().ImagesFormat) > 0 && !options.quiet { 89 format = dockerCLI.ConfigFile().ImagesFormat 90 } else { 91 format = formatter.TableFormatKey 92 } 93 } 94 95 imageCtx := formatter.ImageContext{ 96 Context: formatter.Context{ 97 Output: dockerCLI.Out(), 98 Format: formatter.NewImageFormat(format, options.quiet, options.showDigests), 99 Trunc: !options.noTrunc, 100 }, 101 Digest: options.showDigests, 102 } 103 if err := formatter.ImageWrite(imageCtx, images); err != nil { 104 return err 105 } 106 if options.matchName != "" && len(images) == 0 && options.calledAs == "images" { 107 printAmbiguousHint(dockerCLI.Err(), options.matchName) 108 } 109 return nil 110 } 111 112 // printAmbiguousHint prints an informational warning if the provided filter 113 // argument is ambiguous. 114 // 115 // The "docker images" top-level subcommand predates the "docker <object> <verb>" 116 // convention (e.g. "docker image ls"), but accepts a positional argument to 117 // search/filter images by name (globbing). It's common for users to accidentally 118 // mistake these commands, and to use (e.g.) "docker images ls", expecting 119 // to see all images, but ending up with an empty list because no image named 120 // "ls" was found. 121 // 122 // Disallowing these search-terms would be a breaking change, but we can print 123 // and informational message to help the users correct their mistake. 124 func printAmbiguousHint(stdErr io.Writer, matchName string) { 125 switch matchName { 126 // List of subcommands for "docker image" and their aliases (see "docker image --help"): 127 case "build", 128 "history", 129 "import", 130 "inspect", 131 "list", 132 "load", 133 "ls", 134 "prune", 135 "pull", 136 "push", 137 "rm", 138 "save", 139 "tag": 140 141 _, _ = fmt.Fprintf(stdErr, "\nNo images found matching %q: did you mean \"docker image %[1]s\"?\n", matchName) 142 } 143 }