mirror of
https://github.com/containers/podman.git
synced 2025-07-04 18:27:33 +08:00
Add since
as valid filter option for volume
subcommands
Adds support for `since` as a valid filter option for `podman volume ls` and `podman volume prune`. Implements: #19228 Initially suggested from: #19119 Signed-off-by: Jake Correnti <jakecorrenti+github@proton.me>
This commit is contained in:
@ -23,15 +23,16 @@ which is exclusive. Filters with different keys always work exclusive.
|
||||
|
||||
Volumes can be filtered by the following attributes:
|
||||
|
||||
| **Filter** | **Description** |
|
||||
| ---------- | ------------------------------------------------------------------------------------- |
|
||||
| dangling | [Dangling] Matches all volumes not referenced by any containers |
|
||||
| driver | [Driver] Matches volumes based on their driver |
|
||||
| label | [Key] or [Key=Value] Label assigned to a volume |
|
||||
| name | [Name] Volume name (accepts regex) |
|
||||
| opt | Matches a storage driver options |
|
||||
| scope | Filters volume by scope |
|
||||
| until | Only remove volumes created before given timestamp |
|
||||
| **Filter** | **Description** |
|
||||
| ---------- | ------------------------------------------------------------------------------------- |
|
||||
| dangling | [Dangling] Matches all volumes not referenced by any containers |
|
||||
| driver | [Driver] Matches volumes based on their driver |
|
||||
| label | [Key] or [Key=Value] Label assigned to a volume |
|
||||
| name | [Name] Volume name (accepts regex) |
|
||||
| opt | Matches a storage driver options |
|
||||
| scope | Filters volume by scope |
|
||||
| after/since | Filter by volumes created after the given VOLUME (name or tag) |
|
||||
| until | Only remove volumes created before given timestamp |
|
||||
|
||||
#### **--format**=*format*
|
||||
|
||||
|
@ -26,7 +26,8 @@ Supported filters:
|
||||
| Filter | Description |
|
||||
| :----------------: | --------------------------------------------------------------------------- |
|
||||
| *label* | Only remove volumes, with (or without, in the case of label!=[...] is used) the specified labels. |
|
||||
| *until* | Only remove volumes created before given timestamp. |
|
||||
| *until* | Only remove volumes created before given timestamp. |
|
||||
| *after/since* | Filter by volumes created after the given VOLUME (name or tag) |
|
||||
|
||||
The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*key*=*value*, which removes volumes with the specified labels. The other format is the `label!`=*key* or `label!`=*key*=*value*, which removes volumes without the specified labels.
|
||||
|
||||
|
@ -44,7 +44,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
volumeFilters := []libpod.VolumeFilter{}
|
||||
for filter, filterValues := range *filtersMap {
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, filterValues)
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, filterValues, runtime)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
}
|
||||
@ -276,7 +276,7 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
|
||||
f := (url.Values)(*filterMap)
|
||||
filterFuncs := []libpod.VolumeFilter{}
|
||||
for filter, filterValues := range f {
|
||||
filterFunc, err := filters.GeneratePruneVolumeFilters(filter, filterValues)
|
||||
filterFunc, err := filters.GeneratePruneVolumeFilters(filter, filterValues, runtime)
|
||||
if err != nil {
|
||||
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse filters for %s: %w", f.Encode(), err))
|
||||
return
|
||||
|
@ -121,7 +121,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
volumeFilters := []libpod.VolumeFilter{}
|
||||
for filter, filterValues := range *filterMap {
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, filterValues)
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, filterValues, runtime)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
@ -168,7 +168,7 @@ func pruneVolumesHelper(r *http.Request) ([]*reports.PruneReport, error) {
|
||||
f := (url.Values)(*filterMap)
|
||||
filterFuncs := []libpod.VolumeFilter{}
|
||||
for filter, filterValues := range f {
|
||||
filterFunc, err := filters.GeneratePruneVolumeFilters(filter, filterValues)
|
||||
filterFunc, err := filters.GeneratePruneVolumeFilters(filter, filterValues, runtime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -3,14 +3,17 @@ package filters
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/pkg/filters"
|
||||
"github.com/containers/podman/v4/libpod"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
)
|
||||
|
||||
func GenerateVolumeFilters(filter string, filterValues []string) (libpod.VolumeFilter, error) {
|
||||
func GenerateVolumeFilters(filter string, filterValues []string, runtime *libpod.Runtime) (libpod.VolumeFilter, error) {
|
||||
switch filter {
|
||||
case "after", "since":
|
||||
return createAfterFilterVolumeFunction(filterValues, runtime)
|
||||
case "name":
|
||||
return func(v *libpod.Volume) bool {
|
||||
return util.StringMatchRegexSlice(v.Name(), filterValues)
|
||||
@ -98,8 +101,10 @@ func GenerateVolumeFilters(filter string, filterValues []string) (libpod.VolumeF
|
||||
return nil, fmt.Errorf("%q is an invalid volume filter", filter)
|
||||
}
|
||||
|
||||
func GeneratePruneVolumeFilters(filter string, filterValues []string) (libpod.VolumeFilter, error) {
|
||||
func GeneratePruneVolumeFilters(filter string, filterValues []string, runtime *libpod.Runtime) (libpod.VolumeFilter, error) {
|
||||
switch filter {
|
||||
case "after", "since":
|
||||
return createAfterFilterVolumeFunction(filterValues, runtime)
|
||||
case "label":
|
||||
return func(v *libpod.Volume) bool {
|
||||
return filters.MatchLabelFilters(filterValues, v.Labels())
|
||||
@ -126,3 +131,19 @@ func createUntilFilterVolumeFunction(filterValues []string) (libpod.VolumeFilter
|
||||
return false
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createAfterFilterVolumeFunction(filterValues []string, runtime *libpod.Runtime) (libpod.VolumeFilter, error) {
|
||||
var createTime time.Time
|
||||
for _, filterValue := range filterValues {
|
||||
vol, err := runtime.LookupVolume(filterValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if createTime.IsZero() || createTime.After(vol.CreatedTime()) {
|
||||
createTime = vol.CreatedTime()
|
||||
}
|
||||
}
|
||||
return func(v *libpod.Volume) bool {
|
||||
return createTime.Before(v.CreatedTime())
|
||||
}, nil
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
|
||||
func (ic *ContainerEngine) VolumePrune(ctx context.Context, options entities.VolumePruneOptions) ([]*reports.PruneReport, error) {
|
||||
funcs := []libpod.VolumeFilter{}
|
||||
for filter, filterValues := range options.Filters {
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, filterValues)
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, filterValues, ic.Libpod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -144,7 +144,7 @@ func (ic *ContainerEngine) pruneVolumesHelper(ctx context.Context, filterFuncs [
|
||||
func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeListOptions) ([]*entities.VolumeListReport, error) {
|
||||
volumeFilters := []libpod.VolumeFilter{}
|
||||
for filter, value := range opts.Filter {
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, value)
|
||||
filterFunc, err := filters.GenerateVolumeFilters(filter, value, ic.Libpod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -211,4 +211,34 @@ var _ = Describe("Podman volume ls", func() {
|
||||
Expect(session.OutputToStringArray()).To(HaveLen(1))
|
||||
Expect(session.OutputToStringArray()[0]).To(Equal(vol3Name))
|
||||
})
|
||||
|
||||
It("podman ls volume with --filter since/after", func() {
|
||||
vol1 := "vol1"
|
||||
vol2 := "vol2"
|
||||
vol3 := "vol3"
|
||||
|
||||
session := podmanTest.Podman([]string{"volume", "create", vol1})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "create", vol2})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "create", vol3})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "ls", "-q", "--filter", "since=" + vol1})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.OutputToStringArray()).To(HaveLen(2))
|
||||
Expect(session.OutputToStringArray()[0]).To(Equal(vol2))
|
||||
Expect(session.OutputToStringArray()[1]).To(Equal(vol3))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "ls", "-q", "--filter", "after=" + vol1})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.OutputToStringArray()).To(HaveLen(2))
|
||||
Expect(session.OutputToStringArray()[0]).To(Equal(vol2))
|
||||
Expect(session.OutputToStringArray()[1]).To(Equal(vol3))
|
||||
})
|
||||
})
|
||||
|
@ -163,4 +163,31 @@ var _ = Describe("Podman volume prune", func() {
|
||||
Expect(session).Should(Exit(0))
|
||||
Expect(session.OutputToStringArray()).To(BeEmpty())
|
||||
})
|
||||
|
||||
It("podman volume prune --filter since/after", func() {
|
||||
vol1 := "vol1"
|
||||
vol2 := "vol2"
|
||||
vol3 := "vol3"
|
||||
|
||||
session := podmanTest.Podman([]string{"volume", "create", vol1})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "create", vol2})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "create", vol3})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "prune", "-f", "--filter", "since=" + vol1})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "ls", "-q"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.OutputToStringArray()).To(HaveLen(1))
|
||||
Expect(session.OutputToStringArray()[0]).To(Equal(vol1))
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user