mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #31538 from yongtang/31325-service-ls-filter-mode
Support `--filter mode=global|replicated` for `docker service ls`
This commit is contained in:
commit
b36ce6f2f6
6 changed files with 77 additions and 18 deletions
|
@ -7399,6 +7399,7 @@ paths:
|
||||||
|
|
||||||
- `id=<service id>`
|
- `id=<service id>`
|
||||||
- `label=<service label>`
|
- `label=<service label>`
|
||||||
|
- `mode=["replicated"|"global"]`
|
||||||
- `name=<service name>`
|
- `name=<service name>`
|
||||||
tags: ["Service"]
|
tags: ["Service"]
|
||||||
/services/create:
|
/services/create:
|
||||||
|
|
|
@ -45,22 +45,6 @@ func newListNodesFilters(filter filters.Args) (*swarmapi.ListNodesRequest_Filter
|
||||||
return f, nil
|
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) {
|
func newListTasksFilters(filter filters.Args, transformFunc func(filters.Args) error) (*swarmapi.ListTasksRequest_Filters, error) {
|
||||||
accepted := map[string]bool{
|
accepted := map[string]bool{
|
||||||
"name": true,
|
"name": true,
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/docker/docker/daemon/logger"
|
"github.com/docker/docker/daemon/logger"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
"github.com/docker/docker/pkg/stdcopy"
|
||||||
|
runconfigopts "github.com/docker/docker/runconfig/opts"
|
||||||
swarmapi "github.com/docker/swarmkit/api"
|
swarmapi "github.com/docker/swarmkit/api"
|
||||||
gogotypes "github.com/gogo/protobuf/types"
|
gogotypes "github.com/gogo/protobuf/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -37,10 +38,25 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv
|
||||||
return nil, c.errNoManager(state)
|
return nil, c.errNoManager(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
filters, err := newListServicesFilters(options.Filters)
|
// We move the accepted filter check here as "mode" filter
|
||||||
if err != nil {
|
// 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
|
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()
|
ctx, cancel := c.getRequestContext()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -54,6 +70,19 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv
|
||||||
services := []types.Service{}
|
services := []types.Service{}
|
||||||
|
|
||||||
for _, service := range r.Services {
|
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))
|
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 /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 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.
|
* `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
|
## v1.27 API changes
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ The currently supported filters are:
|
||||||
|
|
||||||
* [id](service_ls.md#id)
|
* [id](service_ls.md#id)
|
||||||
* [label](service_ls.md#label)
|
* [label](service_ls.md#label)
|
||||||
|
* [mode](service_ls.md#mode)
|
||||||
* [name](service_ls.md#name)
|
* [name](service_ls.md#name)
|
||||||
|
|
||||||
#### id
|
#### id
|
||||||
|
@ -98,6 +99,18 @@ ID NAME MODE REPLICAS IMAGE
|
||||||
74nzcxxjv6fq backend replicated 3/3 redis:3.0.6
|
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
|
#### name
|
||||||
|
|
||||||
The `name` filter matches on all or part of a service's 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(err, checker.IsNil, check.Commentf(out))
|
||||||
c.Assert(strings.TrimSpace(out), checker.Equals, "SIGUSR1")
|
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")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue