Skip to content

Commit d95ff1a

Browse files
Merge pull request containers#10756 from jmguzik/volume-prune-until-http-api
Add support for volume prune until filter to http api
2 parents 3f3feaa + a0b24de commit d95ff1a

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

pkg/api/server/register_volumes.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
8888
// description: |
8989
// JSON encoded value of filters (a map[string][]string) to match volumes against before pruning.
9090
// Available filters:
91-
// - label (label=<key>, label=<key>=<value>, label!=<key>, or label!=<key>=<value>) Prune volumes with (or without, in case label!=... is used) the specified labels.
91+
// - `until=<timestamp>` Prune volumes created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time.
92+
// - `label` (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune volumes with (or without, in case `label!=...` is used) the specified labels.
9293
// responses:
9394
// '200':
9495
// "$ref": "#/responses/VolumePruneResponse"
@@ -268,7 +269,8 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
268269
// description: |
269270
// JSON encoded value of filters (a map[string][]string) to match volumes against before pruning.
270271
// Available filters:
271-
// - label (label=<key>, label=<key>=<value>, label!=<key>, or label!=<key>=<value>) Prune volumes with (or without, in case label!=... is used) the specified labels.
272+
// - `until=<timestamp>` Prune volumes created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time.
273+
// - `label` (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune volumes with (or without, in case `label!=...` is used) the specified labels.
272274
// responses:
273275
// '200':
274276
// "$ref": "#/responses/DockerVolumePruneResponse"

pkg/domain/filters/volumes.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,22 @@ func GeneratePruneVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, erro
8686
var vf []libpod.VolumeFilter
8787
for filter, v := range filters {
8888
for _, val := range v {
89+
filterVal := val
8990
switch filter {
9091
case "label":
91-
filter := val
9292
vf = append(vf, func(v *libpod.Volume) bool {
93-
return util.MatchLabelFilters([]string{filter}, v.Labels())
93+
return util.MatchLabelFilters([]string{filterVal}, v.Labels())
94+
})
95+
case "until":
96+
until, err := util.ComputeUntilTimestamp([]string{filterVal})
97+
if err != nil {
98+
return nil, err
99+
}
100+
vf = append(vf, func(v *libpod.Volume) bool {
101+
if !until.IsZero() && v.CreatedTime().Before(until) {
102+
return true
103+
}
104+
return false
94105
})
95106
default:
96107
return nil, errors.Errorf("%q is an invalid volume filter", filter)

test/apiv2/30-volumes.at

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,6 @@ t POST libpod/volumes/prune?filters='{"label":["tes' 500 \
125125
t POST libpod/volumes/prune?filters='{"label":["testlabel"]}' 200
126126
t GET libpod/volumes/json?filters='{"label":["testlabel"]}' 200 length=0
127127

128-
## Prune volumes
129-
t POST libpod/volumes/prune 200
130-
#After prune volumes, there should be no volume existing
131-
t GET libpod/volumes/json 200 length=0
132-
133128
# libpod api: do not use list filters for prune
134129
t POST libpod/volumes/prune?filters='{"name":["anyname"]}' 500 \
135130
.cause="\"name\" is an invalid volume filter"
@@ -146,4 +141,46 @@ t POST volumes/prune?filters='{"driver":["anydriver"]}' 500 \
146141
t POST volumes/prune?filters='{"scope":["anyscope"]}' 500 \
147142
.cause="\"scope\" is an invalid volume filter"
148143

144+
## Prune volumes using until filter
145+
t POST libpod/volumes/create \
146+
Name=foo5 \
147+
Label='{"testuntil":""}' \
148+
Options='{"type":"tmpfs","o":"nodev,noexec"}}' \
149+
201 \
150+
.Name=foo5 \
151+
.Labels.testuntil="" \
152+
.Options.type=tmpfs \
153+
.Options.o=nodev,noexec
154+
155+
# with date way back in the past, volume should not be deleted
156+
t POST libpod/volumes/prune?filters='{"until":["500000"]}' 200
157+
t GET libpod/volumes/json?filters='{"label":["testuntil"]}' 200 length=1
158+
159+
# with date far in the future, volume should be deleted
160+
t POST libpod/volumes/prune?filters='{"until":["5000000000"]}' 200
161+
t GET libpod/volumes/json?filters='{"label":["testuntil"]}' 200 length=0
162+
163+
t POST libpod/volumes/create \
164+
Name=foo6 \
165+
Label='{"testuntilcompat":""}' \
166+
Options='{"type":"tmpfs","o":"nodev,noexec"}}' \
167+
201 \
168+
.Name=foo6 \
169+
.Labels.testuntilcompat="" \
170+
.Options.type=tmpfs \
171+
.Options.o=nodev,noexec
172+
173+
# with date way back in the past, volume should not be deleted (compat api)
174+
t POST volumes/prune?filters='{"until":["500000"]}' 200
175+
t GET libpod/volumes/json?filters='{"label":["testuntilcompat"]}' 200 length=1
176+
177+
# with date far in the future, volume should be deleted (compat api)
178+
t POST volumes/prune?filters='{"until":["5000000000"]}' 200
179+
t GET libpod/volumes/json?filters='{"label":["testuntilcompat"]}' 200 length=0
180+
181+
## Prune volumes
182+
t POST libpod/volumes/prune 200
183+
#After prune volumes, there should be no volume existing
184+
t GET libpod/volumes/json 200 length=0
185+
149186
# vim: filetype=sh

0 commit comments

Comments
 (0)