mirror of
https://github.com/containers/podman.git
synced 2025-05-20 08:36:23 +08:00
Merge pull request #4596 from kunalkushwaha/container-prune
container prune command fixed as per docker prune command
This commit is contained in:
@ -184,6 +184,7 @@ type PruneImagesValues struct {
|
||||
type PruneContainersValues struct {
|
||||
PodmanCommand
|
||||
Force bool
|
||||
Filter []string
|
||||
}
|
||||
|
||||
type PodPruneValues struct {
|
||||
|
@ -1,6 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
@ -36,9 +41,23 @@ 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 {
|
||||
if !c.Force {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Printf(`WARNING! This will remove all stopped containers.
|
||||
Are you sure you want to continue? [y/N] `)
|
||||
ans, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error reading input")
|
||||
}
|
||||
if strings.ToLower(ans)[0] != 'y' {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
@ -49,7 +68,7 @@ func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
|
||||
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 {
|
||||
|
@ -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"
|
||||
@ -274,7 +275,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 {
|
||||
@ -396,6 +398,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)
|
||||
}
|
||||
@ -413,7 +431,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")
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -2832,9 +2832,12 @@ _podman_images_prune() {
|
||||
|
||||
_podman_container_prune() {
|
||||
local options_with_args="
|
||||
--filter
|
||||
"
|
||||
|
||||
local boolean_options="
|
||||
-f
|
||||
--force
|
||||
-h
|
||||
--help
|
||||
"
|
||||
|
@ -20,6 +20,8 @@ Print usage statement
|
||||
Remove all stopped containers from local storage
|
||||
```
|
||||
$ sudo podman container prune
|
||||
WARNING! This will remove all stopped containers.
|
||||
Are you sure you want to continue? [y/N] y
|
||||
878392adf2e6c5c9bb1fc19b69d37d2e98c8abf9d539c0bce4b15b46bbcce471
|
||||
37664467fbe3618bf9479c34393ac29c02696675addf1750f9e346581636cde7
|
||||
ed0c6468b8e1cb641b4621d1fe30cb477e1fefc5c0bceb66feaf2f7cb50e5962
|
||||
@ -28,6 +30,26 @@ fff1c5b6c3631746055ec40598ce8ecaa4b82aef122f9e3a85b03b55c0d06c23
|
||||
602d343cd47e7cb3dfc808282a9900a3e4555747787ec6723bb68cedab8384d5
|
||||
```
|
||||
|
||||
Remove all stopped containers from local storage without confirmation.
|
||||
```
|
||||
$ sudo podman container prune -f
|
||||
878392adf2e6c5c9bb1fc19b69d37d2e98c8abf9d539c0bce4b15b46bbcce471
|
||||
37664467fbe3618bf9479c34393ac29c02696675addf1750f9e346581636cde7
|
||||
ed0c6468b8e1cb641b4621d1fe30cb477e1fefc5c0bceb66feaf2f7cb50e5962
|
||||
6ac6c8f0067b7a4682e6b8e18902665b57d1a0e07e885d9abcd382232a543ccd
|
||||
fff1c5b6c3631746055ec40598ce8ecaa4b82aef122f9e3a85b03b55c0d06c23
|
||||
602d343cd47e7cb3dfc808282a9900a3e4555747787ec6723bb68cedab8384d5
|
||||
|
||||
```
|
||||
|
||||
Remove all stopped containers from local storage created within last 10 minutes
|
||||
```
|
||||
$ sudo podman container prune --filter until="10m"
|
||||
WARNING! This will remove all stopped containers.
|
||||
Are you sure you want to continue? [y/N] y
|
||||
3d366295e33d8cc612c4d873199bacadd55088d90d17dcafaa9a2d317ad50b4e
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
podman(1), podman-ps
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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{}
|
||||
|
@ -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))
|
||||
|
||||
|
Reference in New Issue
Block a user