From d04375bd4aa85794ef65737525da76ab84b8c8de Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Fri, 29 Jul 2016 08:20:03 -0700 Subject: [PATCH] Support multiple service IDs on "docker service ps" This fix tries to address issue raised in 25228 to support multiple service IDs on `docker service ps`. Multiple IDs are allowed with `docker service ps ...`, and related documentation has been updated. A test has been added to cover the changes. This fix fixes 25228. Signed-off-by: Yong Tang --- command/service/ps.go | 56 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/command/service/ps.go b/command/service/ps.go index cf94ad7374..12b25bf4f6 100644 --- a/command/service/ps.go +++ b/command/service/ps.go @@ -1,7 +1,13 @@ package service import ( + "fmt" + "strings" + + "golang.org/x/net/context" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command/idresolver" @@ -9,11 +15,10 @@ import ( "github.com/docker/docker/cli/command/task" "github.com/docker/docker/opts" "github.com/spf13/cobra" - "golang.org/x/net/context" ) type psOptions struct { - serviceID string + services []string quiet bool noResolve bool noTrunc bool @@ -24,11 +29,11 @@ func newPsCommand(dockerCli *command.DockerCli) *cobra.Command { opts := psOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ - Use: "ps [OPTIONS] SERVICE", - Short: "List the tasks of a service", - Args: cli.ExactArgs(1), + Use: "ps [OPTIONS] SERVICE [SERVICE...]", + Short: "List the tasks of one or more services", + Args: cli.RequiresMinArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - opts.serviceID = args[0] + opts.services = args return runPS(dockerCli, opts) }, } @@ -45,13 +50,46 @@ func runPS(dockerCli *command.DockerCli, opts psOptions) error { client := dockerCli.Client() ctx := context.Background() - service, _, err := client.ServiceInspectWithRaw(ctx, opts.serviceID) + filter := opts.filter.Value() + + serviceIDFilter := filters.NewArgs() + serviceNameFilter := filters.NewArgs() + for _, service := range opts.services { + serviceIDFilter.Add("id", service) + serviceNameFilter.Add("name", service) + } + serviceByIDList, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceIDFilter}) + if err != nil { + return err + } + serviceByNameList, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceNameFilter}) if err != nil { return err } - filter := opts.filter.Value() - filter.Add("service", service.ID) + for _, service := range opts.services { + serviceCount := 0 + // Lookup by ID/Prefix + for _, serviceEntry := range serviceByIDList { + if strings.HasPrefix(serviceEntry.ID, service) { + filter.Add("service", serviceEntry.ID) + serviceCount++ + } + } + + // Lookup by Name/Prefix + for _, serviceEntry := range serviceByNameList { + if strings.HasPrefix(serviceEntry.Spec.Annotations.Name, service) { + filter.Add("service", serviceEntry.ID) + serviceCount++ + } + } + // If nothing has been found, return immediately. + if serviceCount == 0 { + return fmt.Errorf("no such services: %s", service) + } + } + if filter.Include("node") { nodeFilters := filter.Get("node") for _, nodeFilter := range nodeFilters {