Support --filter mode=global|replicated for docker service ls

This fix tries to address the request in 31325 by adding
`--filter mode=global|replicated` to `docker service ls`.

As `docker service ls` has a `MODE` column by default, it is natural
to support `--filter mode=global|replicated` for `docker service ls`.

There are multiple ways to address the issue. One way is to pass
the filter of mode to SwarmKit, another way is to process the filter
of mode in the daemon.

This fix process the filter in the daemon.

Related docs has been updated.

An integration test has been added.

This fix fixes 31325.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Upstream-commit: 43a1bd564b5dbd835631cda102f68286c0d533e9
Component: engine
This commit is contained in:
Yong Tang
2017-03-15 11:06:57 -07:00
parent 143f4ad598
commit f6bac49560
6 changed files with 77 additions and 18 deletions
+1
View File
@@ -7398,6 +7398,7 @@ paths:
- `id=<service id>`
- `label=<service label>`
- `mode=["replicated"|"global"]`
- `name=<service name>`
tags: ["Service"]
/services/create:
@@ -45,22 +45,6 @@ func newListNodesFilters(filter filters.Args) (*swarmapi.ListNodesRequest_Filter
return f, nil
}
func newListServicesFilters(filter filters.Args) (*swarmapi.ListServicesRequest_Filters, error) {
accepted := map[string]bool{
"name": true,
"id": true,
"label": true,
}
if err := filter.Validate(accepted); err != nil {
return nil, err
}
return &swarmapi.ListServicesRequest_Filters{
NamePrefixes: filter.Get("name"),
IDPrefixes: filter.Get("id"),
Labels: runconfigopts.ConvertKVStringsToMap(filter.Get("label")),
}, nil
}
func newListTasksFilters(filter filters.Args, transformFunc func(filters.Args) error) (*swarmapi.ListTasksRequest_Filters, error) {
accepted := map[string]bool{
"name": true,
+31 -2
View File
@@ -21,6 +21,7 @@ import (
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/stdcopy"
runconfigopts "github.com/docker/docker/runconfig/opts"
swarmapi "github.com/docker/swarmkit/api"
gogotypes "github.com/gogo/protobuf/types"
"github.com/pkg/errors"
@@ -37,10 +38,25 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv
return nil, c.errNoManager(state)
}
filters, err := newListServicesFilters(options.Filters)
if err != nil {
// We move the accepted filter check here as "mode" filter
// is processed in the daemon, not in SwarmKit. So it might
// be good to have accepted file check in the same file as
// the filter processing (in the for loop below).
accepted := map[string]bool{
"name": true,
"id": true,
"label": true,
"mode": true,
}
if err := options.Filters.Validate(accepted); err != nil {
return nil, err
}
filters := &swarmapi.ListServicesRequest_Filters{
NamePrefixes: options.Filters.Get("name"),
IDPrefixes: options.Filters.Get("id"),
Labels: runconfigopts.ConvertKVStringsToMap(options.Filters.Get("label")),
}
ctx, cancel := c.getRequestContext()
defer cancel()
@@ -54,6 +70,19 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv
services := []types.Service{}
for _, service := range r.Services {
if options.Filters.Include("mode") {
var mode string
switch service.Spec.GetMode().(type) {
case *swarmapi.ServiceSpec_Global:
mode = "global"
case *swarmapi.ServiceSpec_Replicated:
mode = "replicated"
}
if !options.Filters.ExactMatch("mode", mode) {
continue
}
}
services = append(services, convert.ServiceFromGRPC(*service))
}
@@ -27,6 +27,7 @@ keywords: "API, Docker, rcli, REST, documentation"
* `POST /build` now accepts `extrahosts` parameter to specify a host to ip mapping to use during the build.
* `POST /services/create` and `POST /services/(id or name)/update` now accept a `rollback` value for `FailureAction`.
* `POST /services/create` and `POST /services/(id or name)/update` now accept an optional `RollbackConfig` object which specifies rollback options.
* `GET /services` now supports a `mode` filter to filter services based on the service mode (either `global` or `replicated`).
## v1.27 API changes
@@ -60,6 +60,7 @@ The currently supported filters are:
* [id](service_ls.md#id)
* [label](service_ls.md#label)
* [mode](service_ls.md#mode)
* [name](service_ls.md#name)
#### id
@@ -98,6 +99,18 @@ ID NAME MODE REPLICAS IMAGE
74nzcxxjv6fq backend replicated 3/3 redis:3.0.6
```
#### mode
The `mode` filter matches on the mode (either `replicated` or `global`) of a service.
The following filter matches only `global` services.
```bash
$ docker service ls --filter mode=global
ID NAME MODE REPLICAS IMAGE
w7y0v2yrn620 top global 1/1 busybox
```
#### name
The `name` filter matches on all or part of a service's name.
@@ -1797,3 +1797,34 @@ func (s *DockerSwarmSuite) TestSwarmStopSignal(c *check.C) {
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Equals, "SIGUSR1")
}
func (s *DockerSwarmSuite) TestSwarmServiceLsFilterMode(c *check.C) {
d := s.AddDaemon(c, true, true)
out, err := d.Cmd("service", "create", "--name", "top1", "busybox", "top")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
out, err = d.Cmd("service", "create", "--name", "top2", "--mode=global", "busybox", "top")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
// make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 2)
out, err = d.Cmd("service", "ls")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "top1")
c.Assert(out, checker.Contains, "top2")
c.Assert(out, checker.Not(checker.Contains), "localnet")
out, err = d.Cmd("service", "ls", "--filter", "mode=global")
c.Assert(out, checker.Not(checker.Contains), "top1")
c.Assert(out, checker.Contains, "top2")
c.Assert(err, checker.IsNil, check.Commentf(out))
out, err = d.Cmd("service", "ls", "--filter", "mode=replicated")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "top1")
c.Assert(out, checker.Not(checker.Contains), "top2")
}