1package service // import "github.com/docker/docker/volume/service"
2
3import (
4	"github.com/docker/docker/api/types/filters"
5	"github.com/docker/docker/volume"
6)
7
8// By is an interface which is used to implement filtering on volumes.
9type By interface {
10	isBy()
11}
12
13// ByDriver is `By` that filters based on the driver names that are passed in
14func ByDriver(drivers ...string) By {
15	return byDriver(drivers)
16}
17
18type byDriver []string
19
20func (byDriver) isBy() {}
21
22// ByReferenced is a `By` that filters based on if the volume has references
23type ByReferenced bool
24
25func (ByReferenced) isBy() {}
26
27// And creates a `By` combining all the passed in bys using AND logic.
28func And(bys ...By) By {
29	and := make(andCombinator, 0, len(bys))
30	for _, by := range bys {
31		and = append(and, by)
32	}
33	return and
34}
35
36type andCombinator []By
37
38func (andCombinator) isBy() {}
39
40// Or creates a `By` combining all the passed in bys using OR logic.
41func Or(bys ...By) By {
42	or := make(orCombinator, 0, len(bys))
43	for _, by := range bys {
44		or = append(or, by)
45	}
46	return or
47}
48
49type orCombinator []By
50
51func (orCombinator) isBy() {}
52
53// CustomFilter is a `By` that is used by callers to provide custom filtering
54// logic.
55type CustomFilter filterFunc
56
57func (CustomFilter) isBy() {}
58
59// FromList returns a By which sets the initial list of volumes to use
60func FromList(ls *[]volume.Volume, by By) By {
61	return &fromList{by: by, ls: ls}
62}
63
64type fromList struct {
65	by By
66	ls *[]volume.Volume
67}
68
69func (fromList) isBy() {}
70
71func byLabelFilter(filter filters.Args) By {
72	return CustomFilter(func(v volume.Volume) bool {
73		dv, ok := v.(volume.DetailedVolume)
74		if !ok {
75			return false
76		}
77
78		labels := dv.Labels()
79		if !filter.MatchKVList("label", labels) {
80			return false
81		}
82		if filter.Contains("label!") {
83			if filter.MatchKVList("label!", labels) {
84				return false
85			}
86		}
87		return true
88	})
89}
90