mirror of
https://github.com/containers/podman.git
synced 2025-10-20 12:43:58 +08:00
Merge pull request #10254 from jmguzik/prune-filter-cli
Add support for cli network prune --filter flag
This commit is contained in:
@ -35,6 +35,21 @@ func ReadPodIDFiles(files []string) ([]string, error) {
|
|||||||
return ids, nil
|
return ids, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseFilters transforms one filter format to another and validates input
|
||||||
|
func ParseFilters(filter []string) (map[string][]string, error) {
|
||||||
|
// TODO Remove once filter refactor is finished and url.Values done.
|
||||||
|
filters := map[string][]string{}
|
||||||
|
for _, f := range filter {
|
||||||
|
t := strings.SplitN(f, "=", 2)
|
||||||
|
filters = make(map[string][]string)
|
||||||
|
if len(t) < 2 {
|
||||||
|
return map[string][]string{}, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
|
||||||
|
}
|
||||||
|
filters[t[0]] = append(filters[t[0]], t[1])
|
||||||
|
}
|
||||||
|
return filters, nil
|
||||||
|
}
|
||||||
|
|
||||||
// createExpose parses user-provided exposed port definitions and converts them
|
// createExpose parses user-provided exposed port definitions and converts them
|
||||||
// into SpecGen format.
|
// into SpecGen format.
|
||||||
// TODO: The SpecGen format should really handle ranges more sanely - we could
|
// TODO: The SpecGen format should really handle ranges more sanely - we could
|
||||||
|
|||||||
@ -4,16 +4,15 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/completion"
|
"github.com/containers/common/pkg/completion"
|
||||||
|
"github.com/containers/podman/v3/cmd/podman/common"
|
||||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v3/cmd/podman/utils"
|
"github.com/containers/podman/v3/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,6 +49,7 @@ func init() {
|
|||||||
func prune(cmd *cobra.Command, args []string) error {
|
func prune(cmd *cobra.Command, args []string) error {
|
||||||
var (
|
var (
|
||||||
pruneOptions = entities.ContainerPruneOptions{}
|
pruneOptions = entities.ContainerPruneOptions{}
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
if !force {
|
if !force {
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
@ -64,14 +64,9 @@ func prune(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Remove once filter refactor is finished and url.Values done.
|
pruneOptions.Filters, err = common.ParseFilters(filter)
|
||||||
for _, f := range filter {
|
if err != nil {
|
||||||
t := strings.SplitN(f, "=", 2)
|
return err
|
||||||
pruneOptions.Filters = make(url.Values)
|
|
||||||
if len(t) < 2 {
|
|
||||||
return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
|
|
||||||
}
|
|
||||||
pruneOptions.Filters.Add(t[0], t[1])
|
|
||||||
}
|
}
|
||||||
responses, err := registry.ContainerEngine().ContainerPrune(context.Background(), pruneOptions)
|
responses, err := registry.ContainerEngine().ContainerPrune(context.Background(), pruneOptions)
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containers/common/pkg/completion"
|
||||||
"github.com/containers/podman/v3/cmd/podman/common"
|
"github.com/containers/podman/v3/cmd/podman/common"
|
||||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v3/cmd/podman/utils"
|
"github.com/containers/podman/v3/cmd/podman/utils"
|
||||||
@ -31,12 +32,14 @@ var (
|
|||||||
var (
|
var (
|
||||||
networkPruneOptions entities.NetworkPruneOptions
|
networkPruneOptions entities.NetworkPruneOptions
|
||||||
force bool
|
force bool
|
||||||
|
filter = []string{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func networkPruneFlags(flags *pflag.FlagSet) {
|
func networkPruneFlags(cmd *cobra.Command, flags *pflag.FlagSet) {
|
||||||
//TODO: Not implemented but for future reference
|
|
||||||
//flags.StringSliceVar(&networkPruneOptions.Filters,"filters", []string{}, "provide filter values (e.g. 'until=<timestamp>')")
|
|
||||||
flags.BoolVarP(&force, "force", "f", false, "do not prompt for confirmation")
|
flags.BoolVarP(&force, "force", "f", false, "do not prompt for confirmation")
|
||||||
|
filterFlagName := "filter"
|
||||||
|
flags.StringArrayVar(&filter, filterFlagName, []string{}, "Provide filter values (e.g. 'label=<key>=<value>')")
|
||||||
|
_ = cmd.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -46,12 +49,13 @@ func init() {
|
|||||||
Parent: networkCmd,
|
Parent: networkCmd,
|
||||||
})
|
})
|
||||||
flags := networkPruneCommand.Flags()
|
flags := networkPruneCommand.Flags()
|
||||||
networkPruneFlags(flags)
|
networkPruneFlags(networkPruneCommand, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func networkPrune(cmd *cobra.Command, _ []string) error {
|
func networkPrune(cmd *cobra.Command, _ []string) error {
|
||||||
var (
|
var (
|
||||||
errs utils.OutputErrors
|
errs utils.OutputErrors
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
if !force {
|
if !force {
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
@ -65,6 +69,10 @@ func networkPrune(cmd *cobra.Command, _ []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
networkPruneOptions.Filters, err = common.ParseFilters(filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
responses, err := registry.ContainerEngine().NetworkPrune(registry.Context(), networkPruneOptions)
|
responses, err := registry.ContainerEngine().NetworkPrune(registry.Context(), networkPruneOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setExitCode(err)
|
setExitCode(err)
|
||||||
|
|||||||
@ -13,7 +13,7 @@ Displays a list of existing podman networks.
|
|||||||
#### **--filter**, **-f**
|
#### **--filter**, **-f**
|
||||||
|
|
||||||
Filter output based on conditions given.
|
Filter output based on conditions given.
|
||||||
Multiple filters can be given with multiple uses of the --filter flag.
|
Multiple filters can be given with multiple uses of the --filter option.
|
||||||
Filters with the same key work inclusive with the only exception being
|
Filters with the same key work inclusive with the only exception being
|
||||||
`label` which is exclusive. Filters with different keys always work exclusive.
|
`label` which is exclusive. Filters with different keys always work exclusive.
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,20 @@ the so-called default network which goes by the name of *podman*.
|
|||||||
|
|
||||||
Do not prompt for confirmation
|
Do not prompt for confirmation
|
||||||
|
|
||||||
|
#### **--filter**
|
||||||
|
|
||||||
|
Filter output based on conditions given.
|
||||||
|
Multiple filters can be given with multiple uses of the --filter option.
|
||||||
|
Filters with the same key work inclusive with the only exception being
|
||||||
|
`label` which is exclusive. Filters with different keys always work exclusive.
|
||||||
|
|
||||||
|
Valid filters are listed below:
|
||||||
|
|
||||||
|
| **Filter** | **Description** |
|
||||||
|
| ---------- | ------------------------------------------------------------------------------------- |
|
||||||
|
| label | [Key] or [Key=Value] Label assigned to a network |
|
||||||
|
| until | only remove networks created before given timestamp |
|
||||||
|
|
||||||
## EXAMPLE
|
## EXAMPLE
|
||||||
Prune networks
|
Prune networks
|
||||||
|
|
||||||
|
|||||||
@ -584,6 +584,52 @@ var _ = Describe("Podman network", func() {
|
|||||||
Expect(nc.ExitCode()).To(Equal(0))
|
Expect(nc.ExitCode()).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman network prune --filter", func() {
|
||||||
|
net1 := "macvlan" + stringid.GenerateNonCryptoID() + "net1"
|
||||||
|
|
||||||
|
nc := podmanTest.Podman([]string{"network", "create", net1})
|
||||||
|
nc.WaitWithDefaultTimeout()
|
||||||
|
defer podmanTest.removeCNINetwork(net1)
|
||||||
|
Expect(nc.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
|
list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
|
||||||
|
list.WaitWithDefaultTimeout()
|
||||||
|
Expect(list.ExitCode()).To(BeZero())
|
||||||
|
|
||||||
|
Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue())
|
||||||
|
if !isRootless() {
|
||||||
|
Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
|
||||||
|
}
|
||||||
|
|
||||||
|
// -f needed only to skip y/n question
|
||||||
|
prune := podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=50"})
|
||||||
|
prune.WaitWithDefaultTimeout()
|
||||||
|
Expect(prune.ExitCode()).To(BeZero())
|
||||||
|
|
||||||
|
listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
|
||||||
|
listAgain.WaitWithDefaultTimeout()
|
||||||
|
Expect(listAgain.ExitCode()).To(BeZero())
|
||||||
|
|
||||||
|
Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeTrue())
|
||||||
|
if !isRootless() {
|
||||||
|
Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
|
||||||
|
}
|
||||||
|
|
||||||
|
// -f needed only to skip y/n question
|
||||||
|
prune = podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=5000000000000"})
|
||||||
|
prune.WaitWithDefaultTimeout()
|
||||||
|
Expect(prune.ExitCode()).To(BeZero())
|
||||||
|
|
||||||
|
listAgain = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
|
||||||
|
listAgain.WaitWithDefaultTimeout()
|
||||||
|
Expect(listAgain.ExitCode()).To(BeZero())
|
||||||
|
|
||||||
|
Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse())
|
||||||
|
if !isRootless() {
|
||||||
|
Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
It("podman network prune", func() {
|
It("podman network prune", func() {
|
||||||
// Create two networks
|
// Create two networks
|
||||||
// Check they are there
|
// Check they are there
|
||||||
|
|||||||
Reference in New Issue
Block a user