github.com/kim0/docker@v0.6.2-0.20161130212042-4addda3f07e7/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 type preProcessor struct { 63 types.Container 64 opts *types.ContainerListOptions 65 } 66 67 // Size sets the size option when called by a template execution. 68 func (p *preProcessor) Size() bool { 69 p.opts.Size = true 70 return true 71 } 72 73 // Networks does nothing but return true. 74 // It is needed to avoid the template check to fail as this field 75 // doesn't exist in `types.Container` 76 func (p *preProcessor) Networks() bool { 77 return true 78 } 79 80 func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) { 81 options := &types.ContainerListOptions{ 82 All: opts.all, 83 Limit: opts.last, 84 Size: opts.size, 85 Filter: opts.filter.Value(), 86 } 87 88 if opts.nLatest && opts.last == -1 { 89 options.Limit = 1 90 } 91 92 // Currently only used with Size, so we can determine if the user 93 // put {{.Size}} in their format. 94 pre := &preProcessor{opts: options} 95 tmpl, err := templates.Parse(opts.format) 96 97 if err != nil { 98 return nil, err 99 } 100 101 // This shouldn't error out but swallowing the error makes it harder 102 // to track down if preProcessor issues come up. Ref #24696 103 if err := tmpl.Execute(ioutil.Discard, pre); err != nil { 104 return nil, err 105 } 106 107 return options, nil 108 } 109 110 func runPs(dockerCli *command.DockerCli, opts *psOptions) error { 111 ctx := context.Background() 112 113 listOptions, err := buildContainerListOptions(opts) 114 if err != nil { 115 return err 116 } 117 118 containers, err := dockerCli.Client().ContainerList(ctx, *listOptions) 119 if err != nil { 120 return err 121 } 122 123 format := opts.format 124 if len(format) == 0 { 125 if len(dockerCli.ConfigFile().PsFormat) > 0 && !opts.quiet { 126 format = dockerCli.ConfigFile().PsFormat 127 } else { 128 format = formatter.TableFormatKey 129 } 130 } 131 132 containerCtx := formatter.Context{ 133 Output: dockerCli.Out(), 134 Format: formatter.NewContainerFormat(format, opts.quiet, listOptions.Size), 135 Trunc: !opts.noTrunc, 136 } 137 return formatter.ContainerWrite(containerCtx, containers) 138 }