implement ps --status=xx filter

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2021-06-21 11:01:15 +02:00
parent 796d08d778
commit 3e4f030d2d
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
1 changed files with 55 additions and 6 deletions

View File

@ -24,6 +24,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/docker/compose-cli/cli/formatter" "github.com/docker/compose-cli/cli/formatter"
@ -37,24 +38,52 @@ type psOptions struct {
All bool All bool
Quiet bool Quiet bool
Services 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 { func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
opts := psOptions{ opts := psOptions{
projectOptions: p, projectOptions: p,
} }
psCmd := &cobra.Command{ cmd := &cobra.Command{
Use: "ps", Use: "ps",
Short: "List containers", Short: "List containers",
PreRunE: func(cmd *cobra.Command, args []string) error {
return opts.parseFilter()
},
RunE: Adapt(func(ctx context.Context, args []string) error { RunE: Adapt(func(ctx context.Context, args []string) error {
return runPs(ctx, backend, args, opts) return runPs(ctx, backend, args, opts)
}), }),
} }
psCmd.Flags().StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json].") flags := cmd.Flags()
psCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs") flags.StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json]")
psCmd.Flags().BoolVar(&opts.Services, "services", false, "Display services") flags.StringVar(&opts.Filter, "filter", "", "Filter services by a property")
psCmd.Flags().BoolVarP(&opts.All, "all", "a", false, "Show all stopped containers (including those created by the run command)") flags.StringVar(&opts.Status, "status", "", "Filter services by status")
return psCmd 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 { 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 return nil
} }
if opts.Status != "" {
containers = filterByStatus(containers, opts.Status)
}
sort.Slice(containers, func(i, j int) bool { sort.Slice(containers, func(i, j int) bool {
return containers[i].Name < containers[j].Name 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") "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
}