mirror of
https://github.com/containers/podman.git
synced 2025-07-04 18:27:33 +08:00
Add volume prune --filter support
This change adds support for the `--filter` / `?filters` arguments on the `podman volume prune` subcommand. * Adds ParseFilterArgumentsIntoFilters helper for consistent Filter string slice handling * Adds `--filter` support to podman volume prune cli * Adds `?filters...` support to podman volume prune api * Updates apiv2 / e2e tests Closes #8672 Signed-off-by: Baron Lenardson <lenardson.baron@gmail.com>
This commit is contained in:
@ -8,10 +8,12 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/podman/v2/cmd/podman/common"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/containers/podman/v2/pkg/domain/filters"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -28,6 +30,7 @@ var (
|
||||
RunE: prune,
|
||||
ValidArgsFunction: completion.AutocompleteNone,
|
||||
}
|
||||
filter = []string{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -37,10 +40,17 @@ func init() {
|
||||
Parent: volumeCmd,
|
||||
})
|
||||
flags := pruneCommand.Flags()
|
||||
|
||||
filterFlagName := "filter"
|
||||
flags.StringArrayVar(&filter, filterFlagName, []string{}, "Provide filter values (e.g. 'label=<key>=<value>')")
|
||||
_ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteVolumeFilters)
|
||||
flags.BoolP("force", "f", false, "Do not prompt for confirmation")
|
||||
}
|
||||
|
||||
func prune(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
pruneOptions = entities.VolumePruneOptions{}
|
||||
)
|
||||
// Prompt for confirmation if --force is not set
|
||||
force, err := cmd.Flags().GetBool("force")
|
||||
if err != nil {
|
||||
@ -58,7 +68,11 @@ func prune(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
responses, err := registry.ContainerEngine().VolumePrune(context.Background())
|
||||
pruneOptions.Filters, err = filters.ParseFilterArgumentsIntoFilters(filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
responses, err := registry.ContainerEngine().VolumePrune(context.Background(), pruneOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ podman\-volume\-prune - Remove all unused volumes
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
Removes all unused volumes. You will be prompted to confirm the removal of all the
|
||||
Removes unused volumes. By default all unused volumes will be removed, the **--filter** flag can
|
||||
be used to filter specific volumes. You will be prompted to confirm the removal of all the
|
||||
unused volumes. To bypass the confirmation, use the **--force** flag.
|
||||
|
||||
|
||||
@ -18,6 +19,17 @@ unused volumes. To bypass the confirmation, use the **--force** flag.
|
||||
|
||||
Do not prompt for confirmation.
|
||||
|
||||
#### **--filter**
|
||||
|
||||
Filter volumes to be pruned. Volumes can be filtered by the following attributes:
|
||||
|
||||
- dangling
|
||||
- driver
|
||||
- label
|
||||
- name
|
||||
- opt
|
||||
- scope
|
||||
|
||||
#### **--help**
|
||||
|
||||
Print usage statement
|
||||
@ -29,6 +41,8 @@ Print usage statement
|
||||
$ podman volume prune
|
||||
|
||||
$ podman volume prune --force
|
||||
|
||||
$ podman volume prune --filter label=mylabel=mylabelvalue
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
|
@ -133,9 +133,9 @@ func (r *Runtime) GetAllVolumes() ([]*Volume, error) {
|
||||
}
|
||||
|
||||
// PruneVolumes removes unused volumes from the system
|
||||
func (r *Runtime) PruneVolumes(ctx context.Context) (map[string]error, error) {
|
||||
func (r *Runtime) PruneVolumes(ctx context.Context, filterFuncs []VolumeFilter) (map[string]error, error) {
|
||||
reports := make(map[string]error)
|
||||
vols, err := r.GetAllVolumes()
|
||||
vols, err := r.Volumes(filterFuncs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package compat
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v2/libpod"
|
||||
@ -254,14 +255,15 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
|
||||
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
|
||||
return
|
||||
}
|
||||
// TODO: We have no ability to pass pruning filters to `PruneVolumes()` so
|
||||
// we'll explicitly reject the request if we see any
|
||||
if len(query.Filters) > 0 {
|
||||
utils.InternalServerError(w, errors.New("filters for pruning volumes is not implemented"))
|
||||
|
||||
f := (url.Values)(query.Filters)
|
||||
filterFuncs, err := filters.GenerateVolumeFilters(f)
|
||||
if err != nil {
|
||||
utils.Error(w, "Something when wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse filters for %s", f.Encode()))
|
||||
return
|
||||
}
|
||||
|
||||
pruned, err := runtime.PruneVolumes(r.Context())
|
||||
pruned, err := runtime.PruneVolumes(r.Context(), filterFuncs)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
|
@ -3,6 +3,7 @@ package libpod
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/containers/podman/v2/libpod"
|
||||
"github.com/containers/podman/v2/libpod/define"
|
||||
@ -180,8 +181,25 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
|
||||
func pruneVolumesHelper(r *http.Request) ([]*entities.VolumePruneReport, error) {
|
||||
var (
|
||||
runtime = r.Context().Value("runtime").(*libpod.Runtime)
|
||||
decoder = r.Context().Value("decoder").(*schema.Decoder)
|
||||
)
|
||||
pruned, err := runtime.PruneVolumes(r.Context())
|
||||
query := struct {
|
||||
Filters map[string][]string `schema:"filters"`
|
||||
}{
|
||||
// override any golang type defaults
|
||||
}
|
||||
|
||||
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := (url.Values)(query.Filters)
|
||||
filterFuncs, err := filters.GenerateVolumeFilters(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pruned, err := runtime.PruneVolumes(r.Context(), filterFuncs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -144,16 +144,15 @@ var _ = Describe("Podman volumes", func() {
|
||||
Expect(vols[0].Name).To(Equal("homer"))
|
||||
})
|
||||
|
||||
// TODO we need to add filtering to tests
|
||||
It("prune unused volume", func() {
|
||||
// Pruning when no volumes present should be ok
|
||||
_, err := volumes.Prune(connText)
|
||||
_, err := volumes.Prune(connText, nil)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
// Removing an unused volume should work
|
||||
_, err = volumes.Create(connText, entities.VolumeCreateOptions{})
|
||||
Expect(err).To(BeNil())
|
||||
vols, err := volumes.Prune(connText)
|
||||
vols, err := volumes.Prune(connText, nil)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(len(vols)).To(BeNumerically("==", 1))
|
||||
|
||||
@ -163,11 +162,45 @@ var _ = Describe("Podman volumes", func() {
|
||||
Expect(err).To(BeNil())
|
||||
session := bt.runPodman([]string{"run", "-dt", "-v", fmt.Sprintf("%s:/homer", "homer"), "--name", "vtest", alpine.name, "top"})
|
||||
session.Wait(45)
|
||||
vols, err = volumes.Prune(connText)
|
||||
vols, err = volumes.Prune(connText, nil)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(len(vols)).To(BeNumerically("==", 1))
|
||||
_, err = volumes.Inspect(connText, "homer")
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
// Removing volume with non matching filter shouldn't prune any volumes
|
||||
filters := make(map[string][]string)
|
||||
filters["label"] = []string{"label1=idontmatch"}
|
||||
_, err = volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{
|
||||
"label1": "value1",
|
||||
}})
|
||||
Expect(err).To(BeNil())
|
||||
vols, err = volumes.Prune(connText, filters)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(len(vols)).To(BeNumerically("==", 0))
|
||||
vol2, err := volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{
|
||||
"label1": "value2",
|
||||
}})
|
||||
Expect(err).To(BeNil())
|
||||
_, err = volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{
|
||||
"label1": "value3",
|
||||
}})
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
// Removing volume with matching filter label and value should remove specific entry
|
||||
filters = make(map[string][]string)
|
||||
filters["label"] = []string{"label1=value2"}
|
||||
vols, err = volumes.Prune(connText, filters)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(len(vols)).To(BeNumerically("==", 1))
|
||||
Expect(vols[0].Id).To(Equal(vol2.Name))
|
||||
|
||||
// Removing volumes with matching filter label should remove all matching volumes
|
||||
filters = make(map[string][]string)
|
||||
filters["label"] = []string{"label1"}
|
||||
vols, err = volumes.Prune(connText, filters)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(len(vols)).To(BeNumerically("==", 2))
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -75,7 +75,7 @@ func List(ctx context.Context, filters map[string][]string) ([]*entities.VolumeL
|
||||
}
|
||||
|
||||
// Prune removes unused volumes from the local filesystem.
|
||||
func Prune(ctx context.Context) ([]*entities.VolumePruneReport, error) {
|
||||
func Prune(ctx context.Context, filters map[string][]string) ([]*entities.VolumePruneReport, error) {
|
||||
var (
|
||||
pruned []*entities.VolumePruneReport
|
||||
)
|
||||
@ -83,7 +83,15 @@ func Prune(ctx context.Context) ([]*entities.VolumePruneReport, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/prune", nil, nil)
|
||||
params := url.Values{}
|
||||
if len(filters) > 0 {
|
||||
strFilters, err := bindings.FiltersToString(filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("filters", strFilters)
|
||||
}
|
||||
response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/prune", params, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -80,6 +80,6 @@ type ContainerEngine interface {
|
||||
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IDOrNameResponse, error)
|
||||
VolumeInspect(ctx context.Context, namesOrIds []string, opts InspectOptions) ([]*VolumeInspectReport, []error, error)
|
||||
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
|
||||
VolumePrune(ctx context.Context) ([]*VolumePruneReport, error)
|
||||
VolumePrune(ctx context.Context, options VolumePruneOptions) ([]*VolumePruneReport, error)
|
||||
VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
docker_api_types "github.com/docker/docker/api/types"
|
||||
@ -109,6 +110,12 @@ type VolumeInspectReport struct {
|
||||
*VolumeConfigResponse
|
||||
}
|
||||
|
||||
// VolumePruneOptions describes the options needed
|
||||
// to prune a volume from the CLI
|
||||
type VolumePruneOptions struct {
|
||||
Filters url.Values `json:"filters" schema:"filters"`
|
||||
}
|
||||
|
||||
type VolumePruneReport struct {
|
||||
Err error
|
||||
Id string //nolint
|
||||
|
20
pkg/domain/filters/helpers.go
Normal file
20
pkg/domain/filters/helpers.go
Normal file
@ -0,0 +1,20 @@
|
||||
package filters
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func ParseFilterArgumentsIntoFilters(filters []string) (url.Values, error) {
|
||||
parsedFilters := make(url.Values)
|
||||
for _, f := range filters {
|
||||
t := strings.SplitN(f, "=", 2)
|
||||
if len(t) < 2 {
|
||||
return parsedFilters, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
|
||||
}
|
||||
parsedFilters.Add(t[0], t[1])
|
||||
}
|
||||
return parsedFilters, nil
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
package filters
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/podman/v2/libpod"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func GenerateVolumeFilters(filters map[string][]string) ([]libpod.VolumeFilter, error) {
|
||||
func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) {
|
||||
var vf []libpod.VolumeFilter
|
||||
for filter, v := range filters {
|
||||
for _, val := range v {
|
||||
|
@ -214,7 +214,7 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
|
||||
systemPruneReport.ImagePruneReport.Report.Id = append(systemPruneReport.ImagePruneReport.Report.Id, results...)
|
||||
}
|
||||
if options.Volume {
|
||||
volumePruneReport, err := ic.pruneVolumesHelper(ctx)
|
||||
volumePruneReport, err := ic.pruneVolumesHelper(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -127,12 +127,16 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
|
||||
return reports, errs, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) VolumePrune(ctx context.Context) ([]*entities.VolumePruneReport, error) {
|
||||
return ic.pruneVolumesHelper(ctx)
|
||||
func (ic *ContainerEngine) VolumePrune(ctx context.Context, options entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) {
|
||||
filterFuncs, err := filters.GenerateVolumeFilters(options.Filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ic.pruneVolumesHelper(ctx, filterFuncs)
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) pruneVolumesHelper(ctx context.Context) ([]*entities.VolumePruneReport, error) {
|
||||
pruned, err := ic.Libpod.PruneVolumes(ctx)
|
||||
func (ic *ContainerEngine) pruneVolumesHelper(ctx context.Context, filterFuncs []libpod.VolumeFilter) ([]*entities.VolumePruneReport, error) {
|
||||
pruned, err := ic.Libpod.PruneVolumes(ctx, filterFuncs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
|
||||
return reports, errs, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) VolumePrune(ctx context.Context) ([]*entities.VolumePruneReport, error) {
|
||||
return volumes.Prune(ic.ClientCxt)
|
||||
func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) {
|
||||
return volumes.Prune(ic.ClientCxt, (map[string][]string)(opts.Filters))
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeListOptions) ([]*entities.VolumeListReport, error) {
|
||||
|
@ -20,6 +20,18 @@ t POST libpod/volumes/create \
|
||||
.Labels.testlabel=testonly \
|
||||
.Options.type=tmpfs \
|
||||
.Options.o=nodev,noexec
|
||||
t POST libpod/volumes/create \
|
||||
'"Name":"foo3","Label":{"testlabel":""},"Options":{"type":"tmpfs","o":"nodev,noexec"}}' 201 \
|
||||
.Name=foo3 \
|
||||
.Labels.testlabel="" \
|
||||
.Options.type=tmpfs \
|
||||
.Options.o=nodev,noexec
|
||||
t POST libpod/volumes/create \
|
||||
'"Name":"foo4","Label":{"testlabel1":"testonly"},"Options":{"type":"tmpfs","o":"nodev,noexec"}}' 201 \
|
||||
.Name=foo4 \
|
||||
.Labels.testlabel1=testonly \
|
||||
.Options.type=tmpfs \
|
||||
.Options.o=nodev,noexec
|
||||
|
||||
# Negative test
|
||||
# We have created a volume named "foo1"
|
||||
@ -39,6 +51,12 @@ t GET libpod/volumes/json?filters=%7B%22name%22%3A%5B%22foo1%22%5D%7D 200 length
|
||||
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"]}'
|
||||
t GET libpod/volumes/json?filters=%7B%22name%22%3A%5B%22notexists%22%5D%7D 200 length=0
|
||||
# -G --data-urlencode 'filters={"label":["testlabel"]}'
|
||||
t GET libpod/volumes/json?filters=%7B%22label%22:%5B%22testlabel%22%5D%7D 200 length=2
|
||||
# -G --data-urlencode 'filters={"label":["testlabel=testonly"]}'
|
||||
t GET libpod/volumes/json?filters=%7B%22label%22:%5B%22testlabel=testonly%22%5D%7D 200 length=1
|
||||
# -G --data-urlencode 'filters={"label":["testlabel1=testonly"]}'
|
||||
t GET libpod/volumes/json?filters=%7B%22label%22:%5B%22testlabel1=testonly%22%5D%7D 200 length=1
|
||||
|
||||
## inspect volume
|
||||
t GET libpod/volumes/foo1/json 200 \
|
||||
@ -60,6 +78,18 @@ t DELETE libpod/volumes/foo1 404 \
|
||||
.message~.* \
|
||||
.response=404
|
||||
|
||||
## Prune volumes with label matching 'testlabel1=testonly'
|
||||
# -G --data-urlencode 'filters={"label":["testlabel1=testonly"]}'
|
||||
t POST libpod/volumes/prune?filters=%7B%22label%22:%5B%22testlabel1=testonly%22%5D%7D "" 200
|
||||
# -G --data-urlencode 'filters={"label":["testlabel1=testonly"]}'
|
||||
t GET libpod/volumes/json?filters=%7B%22label%22:%5B%22testlabel1=testonly%22%5D%7D 200 length=0
|
||||
|
||||
## Prune volumes with label matching 'testlabel'
|
||||
# -G --data-urlencode 'filters={"label":["testlabel"]}'
|
||||
t POST libpod/volumes/prune?filters=%7B%22label%22:%5B%22testlabel%22%5D%7D "" 200
|
||||
# -G --data-urlencode 'filters={"label":["testlabel"]}'
|
||||
t GET libpod/volumes/json?filters=%7B%22label%22:%5B%22testlabel%22%5D%7D 200 length=0
|
||||
|
||||
## Prune volumes
|
||||
t POST libpod/volumes/prune "" 200
|
||||
#After prune volumes, there should be no volume existing
|
||||
|
@ -62,6 +62,66 @@ var _ = Describe("Podman volume prune", func() {
|
||||
podmanTest.Cleanup()
|
||||
})
|
||||
|
||||
It("podman prune volume --filter", func() {
|
||||
session := podmanTest.Podman([]string{"volume", "create", "--label", "label1=value1", "myvol1"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "create", "--label", "sharedlabel1=slv1", "myvol2"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "create", "--label", "sharedlabel1=slv2", "myvol3"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "create", "--label", "sharedlabel1", "myvol4"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"create", "-v", "myvol5:/myvol5", ALPINE, "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"create", "-v", "myvol6:/myvol6", ALPINE, "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
Expect(len(session.OutputToStringArray())).To(Equal(7))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "label=label1=value1"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
Expect(len(session.OutputToStringArray())).To(Equal(6))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "label=sharedlabel1=slv1"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
Expect(len(session.OutputToStringArray())).To(Equal(5))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "label=sharedlabel1"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.Podman([]string{"volume", "ls"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
Expect(len(session.OutputToStringArray())).To(Equal(3))
|
||||
|
||||
podmanTest.Cleanup()
|
||||
})
|
||||
|
||||
It("podman system prune --volume", func() {
|
||||
session := podmanTest.Podman([]string{"volume", "create"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
|
Reference in New Issue
Block a user