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