github.com/kunnos/engine@v1.13.1/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 // Label is needed here as it allows the correct pre-processing 78 // because Label() is a method with arguments 79 func (o listOptionsProcessor) Label(name string) string { 80 return "" 81 } 82 83 func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) { 84 options := &types.ContainerListOptions{ 85 All: opts.all, 86 Limit: opts.last, 87 Size: opts.size, 88 Filters: opts.filter.Value(), 89 } 90 91 if opts.nLatest && opts.last == -1 { 92 options.Limit = 1 93 } 94 95 tmpl, err := templates.Parse(opts.format) 96 97 if err != nil { 98 return nil, err 99 } 100 101 optionsProcessor := listOptionsProcessor{} 102 // This shouldn't error out but swallowing the error makes it harder 103 // to track down if preProcessor issues come up. Ref #24696 104 if err := tmpl.Execute(ioutil.Discard, optionsProcessor); err != nil { 105 return nil, err 106 } 107 // At the moment all we need is to capture .Size for preprocessor 108 options.Size = opts.size || optionsProcessor["size"] 109 110 return options, nil 111 } 112 113 func runPs(dockerCli *command.DockerCli, opts *psOptions) error { 114 ctx := context.Background() 115 116 listOptions, err := buildContainerListOptions(opts) 117 if err != nil { 118 return err 119 } 120 121 containers, err := dockerCli.Client().ContainerList(ctx, *listOptions) 122 if err != nil { 123 return err 124 } 125 126 format := opts.format 127 if len(format) == 0 { 128 if len(dockerCli.ConfigFile().PsFormat) > 0 && !opts.quiet { 129 format = dockerCli.ConfigFile().PsFormat 130 } else { 131 format = formatter.TableFormatKey 132 } 133 } 134 135 containerCtx := formatter.Context{ 136 Output: dockerCli.Out(), 137 Format: formatter.NewContainerFormat(format, opts.quiet, listOptions.Size), 138 Trunc: !opts.noTrunc, 139 } 140 return formatter.ContainerWrite(containerCtx, containers) 141 }