Merge pull request #21361 from HackToday/addfilter
Add name/driver filter support for volume
This commit is contained in:
commit
2de29fb9c2
5 changed files with 113 additions and 23 deletions
|
@ -18,6 +18,8 @@ import (
|
|||
|
||||
var acceptedVolumeFilterTags = map[string]bool{
|
||||
"dangling": true,
|
||||
"name": true,
|
||||
"driver": true,
|
||||
}
|
||||
|
||||
var acceptedPsFilterTags = map[string]bool{
|
||||
|
@ -472,8 +474,7 @@ func (daemon *Daemon) transformContainer(container *container.Container, ctx *li
|
|||
// of volumes returned.
|
||||
func (daemon *Daemon) Volumes(filter string) ([]*types.Volume, []string, error) {
|
||||
var (
|
||||
volumesOut []*types.Volume
|
||||
danglingOnly = false
|
||||
volumesOut []*types.Volume
|
||||
)
|
||||
volFilters, err := filters.FromParam(filter)
|
||||
if err != nil {
|
||||
|
@ -484,27 +485,51 @@ func (daemon *Daemon) Volumes(filter string) ([]*types.Volume, []string, error)
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
if volFilters.Include("dangling") {
|
||||
if volFilters.ExactMatch("dangling", "true") || volFilters.ExactMatch("dangling", "1") {
|
||||
danglingOnly = true
|
||||
} else if !volFilters.ExactMatch("dangling", "false") && !volFilters.ExactMatch("dangling", "0") {
|
||||
return nil, nil, fmt.Errorf("Invalid filter 'dangling=%s'", volFilters.Get("dangling"))
|
||||
}
|
||||
}
|
||||
|
||||
volumes, warnings, err := daemon.volumes.List()
|
||||
filterVolumes, err := daemon.filterVolumes(volumes, volFilters)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if volFilters.Include("dangling") {
|
||||
volumes = daemon.volumes.FilterByUsed(volumes, !danglingOnly)
|
||||
}
|
||||
for _, v := range volumes {
|
||||
for _, v := range filterVolumes {
|
||||
volumesOut = append(volumesOut, volumeToAPIType(v))
|
||||
}
|
||||
return volumesOut, warnings, nil
|
||||
}
|
||||
|
||||
// filterVolumes filters volume list according to user specified filter
|
||||
// and returns user chosen volumes
|
||||
func (daemon *Daemon) filterVolumes(vols []volume.Volume, filter filters.Args) ([]volume.Volume, error) {
|
||||
// if filter is empty, return original volume list
|
||||
if filter.Len() == 0 {
|
||||
return vols, nil
|
||||
}
|
||||
|
||||
var retVols []volume.Volume
|
||||
for _, vol := range vols {
|
||||
if filter.Include("name") {
|
||||
if !filter.Match("name", vol.Name()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if filter.Include("driver") {
|
||||
if !filter.Match("driver", vol.DriverName()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
retVols = append(retVols, vol)
|
||||
}
|
||||
danglingOnly := false
|
||||
if filter.Include("dangling") {
|
||||
if filter.ExactMatch("dangling", "true") || filter.ExactMatch("dangling", "1") {
|
||||
danglingOnly = true
|
||||
} else if !filter.ExactMatch("dangling", "false") && !filter.ExactMatch("dangling", "0") {
|
||||
return nil, fmt.Errorf("Invalid filter 'dangling=%s'", filter.Get("dangling"))
|
||||
}
|
||||
retVols = daemon.volumes.FilterByUsed(retVols, !danglingOnly)
|
||||
}
|
||||
return retVols, nil
|
||||
}
|
||||
|
||||
func populateImageFilterByParents(ancestorMap map[image.ID]bool, imageID image.ID, getChildren func(image.ID) []image.ID) {
|
||||
if !ancestorMap[imageID] {
|
||||
for _, id := range getChildren(imageID) {
|
||||
|
|
|
@ -134,6 +134,7 @@ This section lists each version from latest to oldest. Each listing includes a
|
|||
* `POST /containers/create` now allows specifying `nocopy` for named volumes, which disables automatic copying from the container path to the volume.
|
||||
* `POST /auth` now returns an `IdentityToken` when supported by a registry.
|
||||
* `POST /containers/create` with both `Hostname` and `Domainname` fields specified will result in the container's hostname being set to `Hostname`, rather than `Hostname.Domainname`.
|
||||
* `GET /volumes` now supports more filters, new added filters are `name` and `driver`.
|
||||
|
||||
### v1.22 API changes
|
||||
|
||||
|
|
|
@ -2837,7 +2837,10 @@ Status Codes:
|
|||
|
||||
Query Parameters:
|
||||
|
||||
- **filters** - JSON encoded value of the filters (a `map[string][]string`) to process on the volumes list. There is one available filter: `dangling=true`
|
||||
- **filters** - JSON encoded value of the filters (a `map[string][]string`) to process on the volumes list. Available filters:
|
||||
- `name=<volume-name>` Matches all or part of a volume name.
|
||||
- `dangling=<boolean>` When set to `true` (or `1`), returns all volumes that are "dangling" (not in use by a container). When set to `false` (or `0`), only volumes that are in use by one or more containers are returned.
|
||||
- `driver=<volume-driver-name>` Matches all or part of a volume driver name.
|
||||
|
||||
Status Codes:
|
||||
|
||||
|
|
|
@ -14,28 +14,71 @@ parent = "smn_cli"
|
|||
|
||||
List volumes
|
||||
|
||||
-f, --filter=[] Provide filter values (i.e. 'dangling=true')
|
||||
-f, --filter=[] Filter output based on these conditions:
|
||||
- dangling=<boolean> a volume if referenced or not
|
||||
- driver=<string> a volume's driver name
|
||||
- name=<string> a volume's name
|
||||
--help Print usage
|
||||
-q, --quiet Only display volume names
|
||||
|
||||
Lists all the volumes Docker knows about. You can filter using the `-f` or `--filter` flag. The filtering format is a `key=value` pair. To specify more than one filter, pass multiple flags (for example, `--filter "foo=bar" --filter "bif=baz"`)
|
||||
|
||||
There is a single supported filter `dangling=value` which takes a boolean of `true` or `false`.
|
||||
Lists all the volumes Docker knows about. You can filter using the `-f` or `--filter` flag. Refer to the [filtering](#filtering) section for more information about available filter options.
|
||||
|
||||
Example output:
|
||||
|
||||
$ docker volume create --name rose
|
||||
rose
|
||||
$ docker volume create --name rosemary
|
||||
rosemary
|
||||
$docker volume create --name tyler
|
||||
tyler
|
||||
$ docker volume ls
|
||||
DRIVER VOLUME NAME
|
||||
local rose
|
||||
local rosemary
|
||||
local tyler
|
||||
|
||||
## Filtering
|
||||
|
||||
The filtering flag (`-f` or `--filter`) format is of "key=value". If there is more
|
||||
than one filter, then pass multiple flags (e.g., `--filter "foo=bar" --filter "bif=baz"`)
|
||||
|
||||
The currently supported filters are:
|
||||
|
||||
* dangling (boolean - true or false, 0 or 1)
|
||||
* driver (a volume driver's name)
|
||||
* name (a volume's name)
|
||||
|
||||
### dangling
|
||||
|
||||
The `dangling` filter matches on all volumes not referenced by any containers
|
||||
|
||||
$ docker run -d -v tyler:/tmpwork busybox
|
||||
f86a7dd02898067079c99ceacd810149060a70528eff3754d0b0f1a93bd0af18
|
||||
$ docker volume ls -f dangling=true
|
||||
DRIVER VOLUME NAME
|
||||
local rosemary
|
||||
|
||||
### driver
|
||||
|
||||
The `driver` filter matches on all or part of a volume's driver name.
|
||||
|
||||
The following filter matches all volumes with a driver name containing the `local` string.
|
||||
|
||||
$ docker volume ls -f driver=local
|
||||
DRIVER VOLUME NAME
|
||||
local rosemary
|
||||
local tyler
|
||||
|
||||
### name
|
||||
|
||||
The `name` filter matches on all or part of a volume's name.
|
||||
|
||||
The following filter matches all volumes with a name containing the `rose` string.
|
||||
|
||||
$ docker volume ls -f name=rose
|
||||
DRIVER VOLUME NAME
|
||||
local rosemary
|
||||
|
||||
## Related information
|
||||
|
||||
* [volume create](volume_create.md)
|
||||
* [volume inspect](volume_inspect.md)
|
||||
* [volume rm](volume_rm.md)
|
||||
* [Understand Data Volumes](../../userguide/containers/dockervolumes.md)
|
||||
* [Understand Data Volumes](../../userguide/containers/dockervolumes.md)
|
||||
|
|
|
@ -138,6 +138,24 @@ func (s *DockerSuite) TestVolumeCliLsFilterDangling(c *check.C) {
|
|||
c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
|
||||
c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output"))
|
||||
c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output"))
|
||||
|
||||
out, _ = dockerCmd(c, "volume", "ls", "--filter", "name=testisin")
|
||||
c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
|
||||
c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("execpeted volume 'testisinuse1' in output"))
|
||||
c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output"))
|
||||
|
||||
out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=invalidDriver")
|
||||
outArr := strings.Split(strings.TrimSpace(out), "\n")
|
||||
c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
|
||||
|
||||
out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=local")
|
||||
outArr = strings.Split(strings.TrimSpace(out), "\n")
|
||||
c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
|
||||
|
||||
out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=loc")
|
||||
outArr = strings.Split(strings.TrimSpace(out), "\n")
|
||||
c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
|
||||
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestVolumeCliLsErrorWithInvalidFilterName(c *check.C) {
|
||||
|
|
Loading…
Reference in a new issue