github.com/justincormack/cli@v0.0.0-20201215022714-831ebeae9675/cli/command/container/list.go (about) 1 package container 2 3 import ( 4 "context" 5 "io/ioutil" 6 7 "github.com/docker/cli/cli" 8 "github.com/docker/cli/cli/command" 9 "github.com/docker/cli/cli/command/formatter" 10 "github.com/docker/cli/opts" 11 "github.com/docker/cli/templates" 12 "github.com/docker/docker/api/types" 13 "github.com/pkg/errors" 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.Cli) *cobra.Command { 30 options := 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, &options) 38 }, 39 } 40 41 flags := cmd.Flags() 42 43 flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display container IDs") 44 flags.BoolVarP(&options.size, "size", "s", false, "Display total file sizes") 45 flags.BoolVarP(&options.all, "all", "a", false, "Show all containers (default shows just running)") 46 flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") 47 flags.BoolVarP(&options.nLatest, "latest", "l", false, "Show the latest created container (includes all states)") 48 flags.IntVarP(&options.last, "last", "n", -1, "Show n last created containers (includes all states)") 49 flags.StringVarP(&options.format, "format", "", "", "Pretty-print containers using a Go template") 50 flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") 51 52 return cmd 53 } 54 55 func newListCommand(dockerCli command.Cli) *cobra.Command { 56 cmd := *NewPsCommand(dockerCli) 57 cmd.Aliases = []string{"ps", "list"} 58 cmd.Use = "ls [OPTIONS]" 59 return &cmd 60 } 61 62 func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) { 63 options := &types.ContainerListOptions{ 64 All: opts.all, 65 Limit: opts.last, 66 Size: opts.size, 67 Filters: opts.filter.Value(), 68 } 69 70 if opts.nLatest && opts.last == -1 { 71 options.Limit = 1 72 } 73 74 options.Size = opts.size 75 if !options.Size && len(opts.format) > 0 { 76 // The --size option isn't set, but .Size may be used in the template. 77 // Parse and execute the given template to detect if the .Size field is 78 // used. If it is, then automatically enable the --size option. See #24696 79 // 80 // Only requesting container size information when needed is an optimization, 81 // because calculating the size is a costly operation. 82 tmpl, err := templates.NewParse("", opts.format) 83 84 if err != nil { 85 return nil, errors.Wrap(err, "failed to parse template") 86 } 87 88 optionsProcessor := formatter.NewContainerContext() 89 90 // This shouldn't error out but swallowing the error makes it harder 91 // to track down if preProcessor issues come up. 92 if err := tmpl.Execute(ioutil.Discard, optionsProcessor); err != nil { 93 return nil, errors.Wrap(err, "failed to execute template") 94 } 95 96 if _, ok := optionsProcessor.FieldsUsed["Size"]; ok { 97 options.Size = true 98 } 99 } 100 101 return options, nil 102 } 103 104 func runPs(dockerCli command.Cli, options *psOptions) error { 105 ctx := context.Background() 106 107 listOptions, err := buildContainerListOptions(options) 108 if err != nil { 109 return err 110 } 111 112 containers, err := dockerCli.Client().ContainerList(ctx, *listOptions) 113 if err != nil { 114 return err 115 } 116 117 format := options.format 118 if len(format) == 0 { 119 if len(dockerCli.ConfigFile().PsFormat) > 0 && !options.quiet { 120 format = dockerCli.ConfigFile().PsFormat 121 } else { 122 format = formatter.TableFormatKey 123 } 124 } 125 126 containerCtx := formatter.Context{ 127 Output: dockerCli.Out(), 128 Format: formatter.NewContainerFormat(format, options.quiet, listOptions.Size), 129 Trunc: !options.noTrunc, 130 } 131 return formatter.ContainerWrite(containerCtx, containers) 132 }