github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/cli/command/container/list.go (about) 1 package container 2 3 import ( 4 "io/ioutil" 5 6 "golang.org/x/net/context" 7 8 "github.com/docker/docker/api/types" 9 "github.com/docker/docker/cli" 10 "github.com/docker/docker/cli/command" 11 "github.com/docker/docker/cli/command/formatter" 12 "github.com/docker/docker/opts" 13 "github.com/docker/docker/utils/templates" 14 "github.com/spf13/cobra" 15 ) 16 17 type psOptions struct { 18 quiet bool 19 size bool 20 all bool 21 noTrunc bool 22 nLatest bool 23 last int 24 format string 25 filter opts.FilterOpt 26 } 27 28 // NewPsCommand creates a new cobra.Command for `docker ps` 29 func NewPsCommand(dockerCli *command.DockerCli) *cobra.Command { 30 opts := psOptions{filter: opts.NewFilterOpt()} 31 32 cmd := &cobra.Command{ 33 Use: "ps [OPTIONS]", 34 Short: "List containers", 35 Args: cli.NoArgs, 36 RunE: func(cmd *cobra.Command, args []string) error { 37 return runPs(dockerCli, &opts) 38 }, 39 } 40 41 flags := cmd.Flags() 42 43 flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display numeric IDs") 44 flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes") 45 flags.BoolVarP(&opts.all, "all", "a", false, "Show all containers (default shows just running)") 46 flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output") 47 flags.BoolVarP(&opts.nLatest, "latest", "l", false, "Show the latest created container (includes all states)") 48 flags.IntVarP(&opts.last, "last", "n", -1, "Show n last created containers (includes all states)") 49 flags.StringVarP(&opts.format, "format", "", "", "Pretty-print containers using a Go template") 50 flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided") 51 52 return cmd 53 } 54 55 func newListCommand(dockerCli *command.DockerCli) *cobra.Command { 56 cmd := *NewPsCommand(dockerCli) 57 cmd.Aliases = []string{"ps", "list"} 58 cmd.Use = "ls [OPTIONS]" 59 return &cmd 60 } 61 62 // listOptionsProcessor is used to set any container list options which may only 63 // be embedded in the format template. 64 // This is passed directly into tmpl.Execute in order to allow the preprocessor 65 // to set any list options that were not provided by flags (e.g. `.Size`). 66 // It is using a `map[string]bool` so that unknown fields passed into the 67 // template format do not cause errors. These errors will get picked up when 68 // running through the actual template processor. 69 type listOptionsProcessor map[string]bool 70 71 // Size sets the size of the map when called by a template execution. 72 func (o listOptionsProcessor) Size() bool { 73 o["size"] = true 74 return true 75 } 76 77 func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) { 78 options := &types.ContainerListOptions{ 79 All: opts.all, 80 Limit: opts.last, 81 Size: opts.size, 82 Filters: opts.filter.Value(), 83 } 84 85 if opts.nLatest && opts.last == -1 { 86 options.Limit = 1 87 } 88 89 tmpl, err := templates.Parse(opts.format) 90 91 if err != nil { 92 return nil, err 93 } 94 95 optionsProcessor := listOptionsProcessor{} 96 // This shouldn't error out but swallowing the error makes it harder 97 // to track down if preProcessor issues come up. Ref #24696 98 if err := tmpl.Execute(ioutil.Discard, optionsProcessor); err != nil { 99 return nil, err 100 } 101 // At the moment all we need is to capture .Size for preprocessor 102 options.Size = opts.size || optionsProcessor["size"] 103 104 return options, nil 105 } 106 107 func runPs(dockerCli *command.DockerCli, opts *psOptions) error { 108 ctx := context.Background() 109 110 listOptions, err := buildContainerListOptions(opts) 111 if err != nil { 112 return err 113 } 114 115 containers, err := dockerCli.Client().ContainerList(ctx, *listOptions) 116 if err != nil { 117 return err 118 } 119 120 format := opts.format 121 if len(format) == 0 { 122 if len(dockerCli.ConfigFile().PsFormat) > 0 && !opts.quiet { 123 format = dockerCli.ConfigFile().PsFormat 124 } else { 125 format = formatter.TableFormatKey 126 } 127 } 128 129 containerCtx := formatter.Context{ 130 Output: dockerCli.Out(), 131 Format: formatter.NewContainerFormat(format, opts.quiet, listOptions.Size), 132 Trunc: !opts.noTrunc, 133 } 134 return formatter.ContainerWrite(containerCtx, containers) 135 }