Merge pull request #21361 from HackToday/addfilter

Add name/driver filter support for volume
This commit is contained in:
Vincent Demeester 2016-03-25 08:07:38 +01:00
commit 2de29fb9c2
5 changed files with 113 additions and 23 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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:

View file

@ -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)

View file

@ -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) {