1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #25234 from yongtang/25228-service-ps-multiple-ID

Support multiple service IDs on "docker service ps"
This commit is contained in:
Vincent Demeester 2017-01-03 12:40:24 +01:00 committed by GitHub
commit 18265591c2
3 changed files with 119 additions and 11 deletions

View file

@ -1,7 +1,13 @@
package service package service
import ( import (
"fmt"
"strings"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/cli" "github.com/docker/docker/cli"
"github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/idresolver" "github.com/docker/docker/cli/command/idresolver"
@ -9,11 +15,10 @@ import (
"github.com/docker/docker/cli/command/task" "github.com/docker/docker/cli/command/task"
"github.com/docker/docker/opts" "github.com/docker/docker/opts"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/net/context"
) )
type psOptions struct { type psOptions struct {
serviceID string services []string
quiet bool quiet bool
noResolve bool noResolve bool
noTrunc bool noTrunc bool
@ -24,11 +29,11 @@ func newPsCommand(dockerCli *command.DockerCli) *cobra.Command {
opts := psOptions{filter: opts.NewFilterOpt()} opts := psOptions{filter: opts.NewFilterOpt()}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "ps [OPTIONS] SERVICE", Use: "ps [OPTIONS] SERVICE [SERVICE...]",
Short: "List the tasks of a service", Short: "List the tasks of one or more services",
Args: cli.ExactArgs(1), Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
opts.serviceID = args[0] opts.services = args
return runPS(dockerCli, opts) return runPS(dockerCli, opts)
}, },
} }
@ -45,13 +50,46 @@ func runPS(dockerCli *command.DockerCli, opts psOptions) error {
client := dockerCli.Client() client := dockerCli.Client()
ctx := context.Background() 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 { if err != nil {
return err return err
} }
filter := opts.filter.Value() for _, service := range opts.services {
filter.Add("service", service.ID) 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") { if filter.Include("node") {
nodeFilters := filter.Get("node") nodeFilters := filter.Get("node")
for _, nodeFilter := range nodeFilters { for _, nodeFilter := range nodeFilters {

View file

@ -19,7 +19,7 @@ aliases: ["/engine/reference/commandline/service_tasks/"]
```Markdown ```Markdown
Usage: docker service ps [OPTIONS] SERVICE Usage: docker service ps [OPTIONS] SERVICE
List the tasks of a service List the tasks of one or more services
Options: Options:
-f, --filter filter Filter output based on conditions provided -f, --filter filter Filter output based on conditions provided
@ -29,7 +29,7 @@ Options:
-q, --quiet Only display task IDs -q, --quiet Only display task IDs
``` ```
Lists the tasks that are running as part of the specified service. This command Lists the tasks that are running as part of the specified services. This command
has to be run targeting a manager node. has to be run targeting a manager node.
## Examples ## Examples

View file

@ -1555,3 +1555,73 @@ func (s *DockerSwarmSuite) TestSwarmNetworkCreateDup(c *check.C) {
} }
} }
} }
func (s *DockerSwarmSuite) TestSwarmServicePsMultipleServiceIDs(c *check.C) {
d := s.AddDaemon(c, true, true)
name1 := "top1"
out, err := d.Cmd("service", "create", "--name", name1, "--replicas=3", "busybox", "top")
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
id1 := strings.TrimSpace(out)
name2 := "top2"
out, err = d.Cmd("service", "create", "--name", name2, "--replicas=3", "busybox", "top")
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
id2 := strings.TrimSpace(out)
// make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 6)
out, err = d.Cmd("service", "ps", name1)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, name1+".1")
c.Assert(out, checker.Contains, name1+".2")
c.Assert(out, checker.Contains, name1+".3")
c.Assert(out, checker.Not(checker.Contains), name2+".1")
c.Assert(out, checker.Not(checker.Contains), name2+".2")
c.Assert(out, checker.Not(checker.Contains), name2+".3")
out, err = d.Cmd("service", "ps", name1, name2)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, name1+".1")
c.Assert(out, checker.Contains, name1+".2")
c.Assert(out, checker.Contains, name1+".3")
c.Assert(out, checker.Contains, name2+".1")
c.Assert(out, checker.Contains, name2+".2")
c.Assert(out, checker.Contains, name2+".3")
// Name Prefix
out, err = d.Cmd("service", "ps", "to")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, name1+".1")
c.Assert(out, checker.Contains, name1+".2")
c.Assert(out, checker.Contains, name1+".3")
c.Assert(out, checker.Contains, name2+".1")
c.Assert(out, checker.Contains, name2+".2")
c.Assert(out, checker.Contains, name2+".3")
// Name Prefix (no hit)
out, err = d.Cmd("service", "ps", "noname")
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "no such services: noname")
out, err = d.Cmd("service", "ps", id1)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, name1+".1")
c.Assert(out, checker.Contains, name1+".2")
c.Assert(out, checker.Contains, name1+".3")
c.Assert(out, checker.Not(checker.Contains), name2+".1")
c.Assert(out, checker.Not(checker.Contains), name2+".2")
c.Assert(out, checker.Not(checker.Contains), name2+".3")
out, err = d.Cmd("service", "ps", id1, id2)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, name1+".1")
c.Assert(out, checker.Contains, name1+".2")
c.Assert(out, checker.Contains, name1+".3")
c.Assert(out, checker.Contains, name2+".1")
c.Assert(out, checker.Contains, name2+".2")
c.Assert(out, checker.Contains, name2+".3")
}