implement ps --status=xx filter
@@ -24,6 +24,7 @@ import (
"sort"
"strings"
+ "github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/docker/compose-cli/cli/formatter"
@@ -37,24 +38,52 @@ type psOptions struct {
All bool
Quiet bool
Services bool
+ Filter string
+ Status string
+}
+
+func (p *psOptions) parseFilter() error {
+ if p.Filter == "" {
+ return nil
+ }
+ parts := strings.SplitN(p.Filter, "=", 2)
+ if len(parts) != 2 {
+ return errors.New("arguments to --filter should be in form KEY=VAL")
+ }
+ switch parts[0] {
+ case "status":
+ p.Status = parts[1]
+ case "source":
+ return api.ErrNotImplemented
+ default:
+ return fmt.Errorf("unknow filter %s", parts[0])
+ }
+ return nil
}
func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
opts := psOptions{
projectOptions: p,
}
- psCmd := &cobra.Command{
+ cmd := &cobra.Command{
Use: "ps",
Short: "List containers",
+ PreRunE: func(cmd *cobra.Command, args []string) error {
+ return opts.parseFilter()
+ },
RunE: Adapt(func(ctx context.Context, args []string) error {
return runPs(ctx, backend, args, opts)
}),
}
- psCmd.Flags().StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
- psCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
- psCmd.Flags().BoolVar(&opts.Services, "services", false, "Display services")
- psCmd.Flags().BoolVarP(&opts.All, "all", "a", false, "Show all stopped containers (including those created by the run command)")
- return psCmd
+ flags := cmd.Flags()
+ flags.StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json]")
+ flags.StringVar(&opts.Filter, "filter", "", "Filter services by a property")
+ flags.StringVar(&opts.Status, "status", "", "Filter services by status")
+ flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
+ flags.BoolVar(&opts.Services, "services", false, "Display services")
+ flags.BoolVarP(&opts.All, "all", "a", false, "Show all stopped containers (including those created by the run command)")
+ flags.Lookup("filter").Hidden = true
+ return cmd
}
func runPs(ctx context.Context, backend api.Service, services []string, opts psOptions) error {
@@ -87,6 +116,10 @@ func runPs(ctx context.Context, backend api.Service, services []string, opts psO
return nil
}
+ if opts.Status != "" {
+ containers = filterByStatus(containers, opts.Status)
+ }
+
sort.Slice(containers, func(i, j int) bool {
return containers[i].Name < containers[j].Name
})
@@ -113,3 +146,19 @@ func runPs(ctx context.Context, backend api.Service, services []string, opts psO
},
"NAME", "SERVICE", "STATUS", "PORTS")
}
+
+func filterByStatus(containers []api.ContainerSummary, status string) []api.ContainerSummary {
+ hasContainerWithState := map[string]struct{}{}
+ for _, c := range containers {
+ if c.State == status {
+ hasContainerWithState[c.Service] = struct{}{}
+ }
+ }
+ var filtered []api.ContainerSummary
+ for _, c := range containers {
+ if _, ok := hasContainerWithState[c.Service]; ok {
+ filtered = append(filtered, c)
+ }
+ }
+ return filtered
+}
