podman-remote prune containers

enable the ability to prune containers from the remote-command.  this
also includes the system prune command.

Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
baude 2019-04-20 12:58:59 -05:00
parent 135c8bef22
commit 2e800d63aa
9 changed files with 97 additions and 48 deletions

View File

@ -46,7 +46,6 @@ func getContainerSubCommands() []*cobra.Command {
_execCommand, _execCommand,
_mountCommand, _mountCommand,
_portCommand, _portCommand,
_pruneContainersCommand,
_refreshCommand, _refreshCommand,
_restoreCommand, _restoreCommand,
_runlabelCommand, _runlabelCommand,
@ -74,7 +73,6 @@ func getTrustSubCommands() []*cobra.Command {
// Commands that the local client implements // Commands that the local client implements
func getSystemSubCommands() []*cobra.Command { func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{ return []*cobra.Command{
_pruneSystemCommand,
_renumberCommand, _renumberCommand,
_dfSystemCommand, _dfSystemCommand,
} }

View File

@ -61,6 +61,7 @@ var (
_logsCommand, _logsCommand,
_pauseCommand, _pauseCommand,
_restartCommand, _restartCommand,
_pruneContainersCommand,
_runCommand, _runCommand,
_rmCommand, _rmCommand,
_startCommand, _startCommand,

View File

@ -1,14 +1,11 @@
package main package main
import ( import (
"context"
"github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -41,39 +38,6 @@ func init() {
flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false") flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
} }
func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWorkers int, force, volumes bool) error {
var deleteFuncs []shared.ParallelWorkerInput
filter := func(c *libpod.Container) bool {
state, err := c.State()
if state == libpod.ContainerStateStopped || (state == libpod.ContainerStateExited && err == nil && c.PodID() == "") {
return true
}
return false
}
delContainers, err := runtime.GetContainers(filter)
if err != nil {
return err
}
if len(delContainers) < 1 {
return nil
}
for _, container := range delContainers {
con := container
f := func() error {
return runtime.RemoveContainer(ctx, con, force, volumes)
}
deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{
ContainerID: con.ID(),
ParallelFunc: f,
})
}
// Run the parallel funcs
deleteErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, deleteFuncs)
return printParallelOutput(deleteErrors, errCount)
}
func pruneContainersCmd(c *cliconfig.PruneContainersValues) error { func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand) runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
@ -81,11 +45,23 @@ func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
maxWorkers := shared.Parallelize("rm") maxWorkers := shared.DefaultPoolSize("prune")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalFlags.MaxWorks maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force)
if err != nil {
return pruneContainers(runtime, getContext(), maxWorkers, c.Bool("force"), c.Bool("volumes")) if errors.Cause(err) == libpod.ErrNoSuchCtr {
if len(c.InputArgs) > 1 {
exitCode = 125
} else {
exitCode = 1
}
}
return err
}
if len(failures) > 0 {
exitCode = 125
}
return printCmdResults(ok, failures)
} }

View File

@ -20,6 +20,7 @@ var (
var systemCommands = []*cobra.Command{ var systemCommands = []*cobra.Command{
_infoCommand, _infoCommand,
_pruneSystemCommand,
} }
func init() { func init() {

View File

@ -81,14 +81,15 @@ Are you sure you want to continue? [y/N] `, volumeString)
rmWorkers := shared.Parallelize("rm") rmWorkers := shared.Parallelize("rm")
ctx := getContext() ctx := getContext()
fmt.Println("Deleted Containers") fmt.Println("Deleted Containers")
lasterr := pruneContainers(runtime, ctx, rmWorkers, false, false) ok, failures, lasterr := runtime.Prune(ctx, rmWorkers, false)
printCmdResults(ok, failures)
fmt.Println("Deleted Pods") fmt.Println("Deleted Pods")
pruneValues := cliconfig.PodPruneValues{ pruneValues := cliconfig.PodPruneValues{
PodmanCommand: c.PodmanCommand, PodmanCommand: c.PodmanCommand,
Force: c.Force, Force: c.Force,
} }
ok, failures, err := runtime.PrunePods(ctx, &pruneValues) ok, failures, err = runtime.PrunePods(ctx, &pruneValues)
if err != nil { if err != nil {
if lasterr != nil { if lasterr != nil {
logrus.Errorf("%q", lasterr) logrus.Errorf("%q", lasterr)

View File

@ -786,3 +786,51 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
} }
return container.Top(descriptors) return container.Top(descriptors)
} }
// Prune removes stopped containers
func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
var (
ok = []string{}
failures = map[string]error{}
err error
)
logrus.Debugf("Setting maximum rm workers to %d", maxWorkers)
filter := func(c *libpod.Container) bool {
state, err := c.State()
if err != nil {
logrus.Error(err)
return false
}
if c.PodID() != "" {
return false
}
if state == libpod.ContainerStateStopped || state == libpod.ContainerStateExited {
return true
}
return false
}
delContainers, err := r.Runtime.GetContainers(filter)
if err != nil {
return ok, failures, err
}
if len(delContainers) < 1 {
return ok, failures, err
}
pool := shared.NewPool("prune", maxWorkers, len(delContainers))
for _, c := range delContainers {
ctr := c
pool.Add(shared.Job{
ID: ctr.ID(),
Fn: func() error {
err := r.Runtime.RemoveContainer(ctx, ctr, force, false)
if err != nil {
logrus.Debugf("Failed to prune container %s: %s", ctr.ID(), err.Error())
}
return err
},
})
}
return pool.Run()
}

View File

@ -852,3 +852,31 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
} }
return iopodman.Top().Call(r.Conn, ctr.ID(), descriptors) return iopodman.Top().Call(r.Conn, ctr.ID(), descriptors)
} }
// Prune removes stopped containers
func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) {
var (
ok = []string{}
failures = map[string]error{}
ctrs []*Container
err error
)
logrus.Debugf("Setting maximum rm workers to %d", maxWorkers)
filters := []string{libpod.ContainerStateExited.String()}
ctrs, err = r.LookupContainersWithStatus(filters)
if err != nil {
return ok, failures, err
}
for _, c := range ctrs {
c := c
_, err := iopodman.RemoveContainer().Call(r.Conn, c.ID(), false, false)
if err != nil {
failures[c.ID()] = err
} else {
ok = append(ok, c.ID())
}
}
return ok, failures, nil
}

View File

@ -13,7 +13,6 @@ import (
) )
func SkipIfRemote() { func SkipIfRemote() {
ginkgo.Skip("This function is not enabled for remote podman")
} }
func SkipIfRootless() { func SkipIfRootless() {

View File

@ -39,7 +39,6 @@ var _ = Describe("Podman prune", func() {
}) })
It("podman container prune containers", func() { It("podman container prune containers", func() {
SkipIfRemote()
top := podmanTest.RunTopContainer("") top := podmanTest.RunTopContainer("")
top.WaitWithDefaultTimeout() top.WaitWithDefaultTimeout()
Expect(top.ExitCode()).To(Equal(0)) Expect(top.ExitCode()).To(Equal(0))
@ -102,8 +101,6 @@ var _ = Describe("Podman prune", func() {
}) })
It("podman system prune pods", func() { It("podman system prune pods", func() {
SkipIfRemote()
session := podmanTest.Podman([]string{"pod", "create"}) session := podmanTest.Podman([]string{"pod", "create"})
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0)) Expect(session.ExitCode()).To(Equal(0))