Make volume filters inclusive

When using multiple filters, return a volume that matches any one of the used filters, rather than matching both of the filters.
This is for compatibility with docker's cli, and more importantly, the apiv2 compat endpoint
Closes #6765

Signed-off-by: Ashley Cui <acui@redhat.com>
This commit is contained in:
Ashley Cui
2020-11-03 14:07:59 -05:00
parent 8dfbdb561b
commit 532bce4ad4
3 changed files with 33 additions and 4 deletions

View File

@ -86,8 +86,8 @@ func (r *Runtime) HasVolume(name string) (bool, error) {
// Volumes retrieves all volumes // Volumes retrieves all volumes
// Filters can be provided which will determine which volumes are included in the // Filters can be provided which will determine which volumes are included in the
// output. Multiple filters are handled by ANDing their output, so only volumes // output. If multiple filters are used, a volume will be returned if
// matching all filters are returned // any of the filters are matched
func (r *Runtime) Volumes(filters ...VolumeFilter) ([]*Volume, error) { func (r *Runtime) Volumes(filters ...VolumeFilter) ([]*Volume, error) {
r.lock.RLock() r.lock.RLock()
defer r.lock.RUnlock() defer r.lock.RUnlock()
@ -101,11 +101,15 @@ func (r *Runtime) Volumes(filters ...VolumeFilter) ([]*Volume, error) {
return nil, err return nil, err
} }
if len(filters) == 0 {
return vols, nil
}
volsFiltered := make([]*Volume, 0, len(vols)) volsFiltered := make([]*Volume, 0, len(vols))
for _, vol := range vols { for _, vol := range vols {
include := true include := false
for _, filter := range filters { for _, filter := range filters {
include = include && filter(vol) include = include || filter(vol)
} }
if include { if include {

View File

@ -35,6 +35,8 @@ t GET libpod/volumes/json 200 \
.[0].CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* .[0].CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.*
# -G --data-urlencode 'filters={"name":["foo1"]}' # -G --data-urlencode 'filters={"name":["foo1"]}'
t GET libpod/volumes/json?filters=%7B%22name%22%3A%5B%22foo1%22%5D%7D 200 length=1 .[0].Name=foo1 t GET libpod/volumes/json?filters=%7B%22name%22%3A%5B%22foo1%22%5D%7D 200 length=1 .[0].Name=foo1
# -G --data-urlencode 'filters={"name":["foo1","foo2"]}'
t GET libpod/volumes/json?filters=%7B%22name%22%3A%20%5B%22foo1%22%2C%20%22foo2%22%5D%7D 200 length=2 .[0].Name=foo1 .[1].Name=foo2
# -G --data-urlencode 'filters={"name":["notexist"]}' # -G --data-urlencode 'filters={"name":["notexist"]}'
t GET libpod/volumes/json?filters=%7B%22name%22%3A%5B%22notexists%22%5D%7D 200 length=0 t GET libpod/volumes/json?filters=%7B%22name%22%3A%5B%22notexists%22%5D%7D 200 length=0

View File

@ -110,4 +110,27 @@ var _ = Describe("Podman volume ls", func() {
Expect(lsDangling.ExitCode()).To(Equal(0)) Expect(lsDangling.ExitCode()).To(Equal(0))
Expect(lsDangling.OutputToString()).To(ContainSubstring(volName1)) Expect(lsDangling.OutputToString()).To(ContainSubstring(volName1))
}) })
It("podman ls volume with multiple --filter flag", func() {
session := podmanTest.Podman([]string{"volume", "create", "--label", "foo=bar", "myvol"})
volName := session.OutputToString()
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"volume", "create", "--label", "foo2=bar2", "anothervol"})
anotherVol := session.OutputToString()
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"volume", "create"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=foo", "--filter", "label=foo2"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(len(session.OutputToStringArray())).To(Equal(3))
Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName))
Expect(session.OutputToStringArray()[2]).To(ContainSubstring(anotherVol))
})
}) })