filter added to container prune command

filter flag helps to filter the containers based on
labels, until(time), name, etc for prune command.

Signed-off-by: Kunal Kushwaha <kunal.kushwaha@gmail.com>
This commit is contained in:
Kunal Kushwaha
2019-11-29 14:28:34 +09:00
parent 0602ce4dc0
commit 10c37a2c93
7 changed files with 49 additions and 13 deletions

View File

@ -184,6 +184,7 @@ type PruneImagesValues struct {
type PruneContainersValues struct {
PodmanCommand
Force bool
Filter []string
}
type PodPruneValues struct {

View File

@ -41,6 +41,7 @@ func init() {
pruneContainersCommand.SetUsageTemplate(UsageTemplate())
flags := pruneContainersCommand.Flags()
flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
flags.StringArrayVar(&pruneContainersCommand.Filter, "filter", []string{}, "Provide filter values (e.g. 'until=<timestamp>')")
}
func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
@ -67,7 +68,7 @@ Are you sure you want to continue? [y/N] `)
if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalFlags.MaxWorks
}
ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force)
ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force, c.Filter)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr {
if len(c.InputArgs) > 1 {

View File

@ -17,6 +17,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/timetype"
"github.com/containers/libpod/pkg/util"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-units"
@ -272,7 +273,8 @@ func worker(wg *sync.WaitGroup, jobs <-chan workerInput, results chan<- PsContai
}
}
func generateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
// GenerateContainerFilterFuncs return ContainerFilter functions based of filter.
func GenerateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
switch filter {
case "id":
return func(c *libpod.Container) bool {
@ -394,6 +396,22 @@ func generateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime)
}
return hcStatus == filterValue
}, nil
case "until":
ts, err := timetype.GetTimestamp(filterValue, time.Now())
if err != nil {
return nil, err
}
seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
if err != nil {
return nil, err
}
until := time.Unix(seconds, nanoseconds)
return func(c *libpod.Container) bool {
if !until.IsZero() && c.CreatedTime().After((until)) {
return true
}
return false
}, nil
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
@ -411,7 +429,7 @@ func GetPsContainerOutput(r *libpod.Runtime, opts PsOptions, filters []string, m
if len(filterSplit) < 2 {
return nil, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
}
generatedFunc, err := generateContainerFilterFuncs(filterSplit[0], filterSplit[1], r)
generatedFunc, err := GenerateContainerFilterFuncs(filterSplit[0], filterSplit[1], r)
if err != nil {
return nil, errors.Wrapf(err, "invalid filter")
}

View File

@ -92,7 +92,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
rmWorkers := shared.Parallelize("rm")
fmt.Println("Deleted Containers")
ok, failures, err = runtime.Prune(ctx, rmWorkers, false)
ok, failures, err = runtime.Prune(ctx, rmWorkers, false, []string{})
if err != nil {
if lasterr != nil {
logrus.Errorf("%q", err)

View File

@ -1009,16 +1009,30 @@ func (r *LocalRuntime) ExecContainer(ctx context.Context, cli *cliconfig.ExecVal
}
// Prune removes stopped containers
func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool, filters []string) ([]string, map[string]error, error) {
var (
ok = []string{}
failures = map[string]error{}
err error
filterFunc []libpod.ContainerFilter
)
logrus.Debugf("Setting maximum rm workers to %d", maxWorkers)
filter := func(c *libpod.Container) bool {
for _, filter := range filters {
filterSplit := strings.SplitN(filter, "=", 2)
if len(filterSplit) < 2 {
return ok, failures, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", filter)
}
f, err := shared.GenerateContainerFilterFuncs(filterSplit[0], filterSplit[1], r.Runtime)
if err != nil {
return ok, failures, err
}
filterFunc = append(filterFunc, f)
}
containerStateFilter := func(c *libpod.Container) bool {
state, err := c.State()
if err != nil {
logrus.Error(err)
@ -1032,7 +1046,9 @@ func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([
}
return false
}
delContainers, err := r.Runtime.GetContainers(filter)
filterFunc = append(filterFunc, containerStateFilter)
delContainers, err := r.Runtime.GetContainers(filterFunc...)
if err != nil {
return ok, failures, err
}

View File

@ -922,7 +922,7 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
}
// Prune removes stopped containers
func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool, filter []string) ([]string, map[string]error, error) {
var (
ok = []string{}

View File

@ -52,7 +52,7 @@ var _ = Describe("Podman prune", func() {
stop.WaitWithDefaultTimeout()
Expect(stop.ExitCode()).To(Equal(0))
prune := podmanTest.Podman([]string{"container", "prune"})
prune := podmanTest.Podman([]string{"container", "prune", "-f"})
prune.WaitWithDefaultTimeout()
Expect(prune.ExitCode()).To(Equal(0))