summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-04-18 06:02:51 -0400
committerGitHub <noreply@github.com>2020-04-18 06:02:51 -0400
commite4e42b28dfef0ffd12f2087048dec61f9cb03976 (patch)
treeebce391a95795cb5861f55380047923fa7184271
parent3b461ed6eb85f329ad163a4f18df3b872fe86f04 (diff)
parent37f3b191d5318b7d25893eabf4e57b568c326773 (diff)
downloadpodman-e4e42b28dfef0ffd12f2087048dec61f9cb03976.tar.gz
podman-e4e42b28dfef0ffd12f2087048dec61f9cb03976.tar.bz2
podman-e4e42b28dfef0ffd12f2087048dec61f9cb03976.zip
Merge pull request #5733 from sujil02/v2-pod-prune
Add pod prune for api v2
-rw-r--r--cmd/podman/pods/prune.go75
-rw-r--r--libpod/runtime_pod.go3
-rw-r--r--pkg/api/handlers/libpod/pods.go11
-rw-r--r--pkg/api/handlers/libpod/swagger.go7
-rw-r--r--pkg/api/server/register_pods.go6
-rw-r--r--pkg/bindings/pods/pods.go12
-rw-r--r--pkg/bindings/test/pods_test.go14
-rw-r--r--pkg/domain/entities/engine_container.go1
-rw-r--r--pkg/domain/entities/pods.go9
-rw-r--r--pkg/domain/entities/types.go2
-rw-r--r--pkg/domain/infra/abi/pods.go17
-rw-r--r--pkg/domain/infra/tunnel/pods.go4
-rw-r--r--test/e2e/pod_prune_test.go23
13 files changed, 144 insertions, 40 deletions
diff --git a/cmd/podman/pods/prune.go b/cmd/podman/pods/prune.go
new file mode 100644
index 000000000..091e3375b
--- /dev/null
+++ b/cmd/podman/pods/prune.go
@@ -0,0 +1,75 @@
+package pods
+
+import (
+ "bufio"
+ "context"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ pruneOptions = entities.PodPruneOptions{}
+)
+
+var (
+ pruneDescription = fmt.Sprintf(`podman pod prune Removes all exited pods`)
+
+ pruneCommand = &cobra.Command{
+ Use: "prune [flags]",
+ Short: "Remove all stopped pods and their containers",
+ Long: pruneDescription,
+ RunE: prune,
+ Example: `podman pod prune`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: pruneCommand,
+ Parent: podCmd,
+ })
+ flags := pruneCommand.Flags()
+ flags.BoolVarP(&pruneOptions.Force, "force", "f", false, "Do not prompt for confirmation. The default is false")
+}
+
+func prune(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ if len(args) > 0 {
+ return errors.Errorf("`%s` takes no arguments", cmd.CommandPath())
+ }
+ if !pruneOptions.Force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Println("WARNING! This will remove all stopped/exited pods..")
+ fmt.Print("Are you sure you want to continue? [y/N] ")
+ answer, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(answer)[0] != 'y' {
+ return nil
+ }
+ }
+ responses, err := registry.ContainerEngine().PodPrune(context.Background(), pruneOptions)
+
+ if err != nil {
+ return err
+ }
+ for _, r := range responses {
+ if r.Err == nil {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Err)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/libpod/runtime_pod.go b/libpod/runtime_pod.go
index be566e211..5b81e166a 100644
--- a/libpod/runtime_pod.go
+++ b/libpod/runtime_pod.go
@@ -176,8 +176,7 @@ func (r *Runtime) GetRunningPods() ([]*Pod, error) {
}
// PrunePods removes unused pods and their containers from local storage.
-// If force is given, then running pods are also included in the pruning.
-func (r *Runtime) PrunePods() (map[string]error, error) {
+func (r *Runtime) PrunePods(ctx context.Context) (map[string]error, error) {
response := make(map[string]error)
states := []string{define.PodStateStopped, define.PodStateExited}
filterFunc := func(p *Pod) bool {
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 92556bb61..618d48ac0 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -232,13 +232,20 @@ func PodRestart(w http.ResponseWriter, r *http.Request) {
func PodPrune(w http.ResponseWriter, r *http.Request) {
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ reports []*entities.PodPruneReport
)
- pruned, err := runtime.PrunePods()
+ responses, err := runtime.PrunePods(r.Context())
if err != nil {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusOK, pruned)
+ for k, v := range responses {
+ reports = append(reports, &entities.PodPruneReport{
+ Err: v,
+ Id: k,
+ })
+ }
+ utils.WriteResponse(w, http.StatusOK, reports)
}
func PodPause(w http.ResponseWriter, r *http.Request) {
diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go
index ed19462c6..46426eb6b 100644
--- a/pkg/api/handlers/libpod/swagger.go
+++ b/pkg/api/handlers/libpod/swagger.go
@@ -70,6 +70,13 @@ type swagStartPodResponse struct {
Body entities.PodStartReport
}
+// Prune pod
+// swagger:response PodPruneReport
+type swagPrunePodResponse struct {
+ // in:body
+ Body entities.PodPruneReport
+}
+
// Rm pod
// swagger:response PodRmReport
type swagRmPodResponse struct {
diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go
index a49bf1f63..63060af41 100644
--- a/pkg/api/server/register_pods.go
+++ b/pkg/api/server/register_pods.go
@@ -53,11 +53,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// - application/json
// responses:
// 200:
- // description: tbd
- // schema:
- // type: object
- // additionalProperties:
- // type: string
+ // $ref: '#/responses/PodPruneReport'
// 400:
// $ref: "#/responses/BadParamError"
// 409:
diff --git a/pkg/bindings/pods/pods.go b/pkg/bindings/pods/pods.go
index 83847614a..3c60fa2a0 100644
--- a/pkg/bindings/pods/pods.go
+++ b/pkg/bindings/pods/pods.go
@@ -98,17 +98,19 @@ func Pause(ctx context.Context, nameOrID string) (*entities.PodPauseReport, erro
return &report, response.Process(&report)
}
-// Prune removes all non-running pods in local storage.
-func Prune(ctx context.Context) error {
+// Prune by default removes all non-running pods in local storage.
+// And with force set true removes all pods.
+func Prune(ctx context.Context) ([]*entities.PodPruneReport, error) {
+ var reports []*entities.PodPruneReport
conn, err := bindings.GetClient(ctx)
if err != nil {
- return err
+ return nil, err
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/prune", nil)
if err != nil {
- return err
+ return nil, err
}
- return response.Process(nil)
+ return reports, response.Process(&reports)
}
// List returns all pods in local storage. The optional filters parameter can
diff --git a/pkg/bindings/test/pods_test.go b/pkg/bindings/test/pods_test.go
index 579161b26..4d682a522 100644
--- a/pkg/bindings/test/pods_test.go
+++ b/pkg/bindings/test/pods_test.go
@@ -262,7 +262,7 @@ var _ = Describe("Podman pods", func() {
var newpod2 string = "newpod2"
bt.Podcreate(&newpod2)
// No pods pruned since no pod in exited state
- err = pods.Prune(bt.conn)
+ pruneResponse, err := pods.Prune(bt.conn)
Expect(err).To(BeNil())
podSummary, err := pods.List(bt.conn, nil)
Expect(err).To(BeNil())
@@ -279,13 +279,19 @@ var _ = Describe("Podman pods", func() {
Expect(err).To(BeNil())
// FIXME sujil please fix this
//Expect(response.State.Status).To(Equal(define.PodStateExited))
- err = pods.Prune(bt.conn)
+ pruneResponse, err = pods.Prune(bt.conn)
Expect(err).To(BeNil())
+ // Validate status and record pod id of pod to be pruned
+ //Expect(response.State.Status).To(Equal(define.PodStateExited))
+ //podID := response.Config.ID
+ // Check if right pod was pruned
+ Expect(len(pruneResponse)).To(Equal(1))
+ // One pod is pruned hence only one pod should be active.
podSummary, err = pods.List(bt.conn, nil)
Expect(err).To(BeNil())
Expect(len(podSummary)).To(Equal(1))
- // Test prune all pods in exited state.
+ // Test prune multiple pods.
bt.Podcreate(&newpod)
_, err = pods.Start(bt.conn, newpod)
Expect(err).To(BeNil())
@@ -311,7 +317,7 @@ var _ = Describe("Podman pods", func() {
Expect(define.StringToContainerStatus(i.State)).
To(Equal(define.ContainerStateStopped))
}
- err = pods.Prune(bt.conn)
+ _, err = pods.Prune(bt.conn)
Expect(err).To(BeNil())
podSummary, err = pods.List(bt.conn, nil)
Expect(err).To(BeNil())
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 02938413a..b730f8743 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -49,6 +49,7 @@ type ContainerEngine interface {
PodPs(ctx context.Context, options PodPSOptions) ([]*ListPodsReport, error)
PodRestart(ctx context.Context, namesOrIds []string, options PodRestartOptions) ([]*PodRestartReport, error)
PodRm(ctx context.Context, namesOrIds []string, options PodRmOptions) ([]*PodRmReport, error)
+ PodPrune(ctx context.Context, options PodPruneOptions) ([]*PodPruneReport, error)
PodStart(ctx context.Context, namesOrIds []string, options PodStartOptions) ([]*PodStartReport, error)
PodStop(ctx context.Context, namesOrIds []string, options PodStopOptions) ([]*PodStopReport, error)
PodTop(ctx context.Context, options PodTopOptions) (*StringSliceReport, error)
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index b280203de..04673ef18 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -147,6 +147,15 @@ func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) {
s.CgroupParent = p.CGroupParent
}
+type PodPruneOptions struct {
+ Force bool `json:"force" schema:"force"`
+}
+
+type PodPruneReport struct {
+ Err error
+ Id string
+}
+
type PodTopOptions struct {
// CLI flags.
ListDescriptors bool
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index e4e1c3ad2..b89aa869a 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -25,9 +25,7 @@ type Report struct {
}
type PodDeleteReport struct{ Report }
-type PodPruneOptions struct{}
-type PodPruneReport struct{ Report }
type VolumeDeleteOptions struct{}
type VolumeDeleteReport struct{ Report }
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 59bf0f636..6b6e13e24 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -243,6 +243,23 @@ func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, optio
return reports, nil
}
+func (ic *ContainerEngine) PodPrune(ctx context.Context, options entities.PodPruneOptions) ([]*entities.PodPruneReport, error) {
+ var (
+ reports []*entities.PodPruneReport
+ )
+ response, err := ic.Libpod.PrunePods(ctx)
+ if err != nil {
+ return nil, err
+ }
+ for k, v := range response {
+ reports = append(reports, &entities.PodPruneReport{
+ Err: v,
+ Id: k,
+ })
+ }
+ return reports, nil
+}
+
func (ic *ContainerEngine) PodCreate(ctx context.Context, opts entities.PodCreateOptions) (*entities.PodCreateReport, error) {
podSpec := specgen.NewPodSpecGenerator()
opts.ToPodSpecGen(podSpec)
diff --git a/pkg/domain/infra/tunnel/pods.go b/pkg/domain/infra/tunnel/pods.go
index dad77284f..e7641c077 100644
--- a/pkg/domain/infra/tunnel/pods.go
+++ b/pkg/domain/infra/tunnel/pods.go
@@ -173,6 +173,10 @@ func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, optio
return reports, nil
}
+func (ic *ContainerEngine) PodPrune(ctx context.Context, opts entities.PodPruneOptions) ([]*entities.PodPruneReport, error) {
+ return pods.Prune(ic.ClientCxt)
+}
+
func (ic *ContainerEngine) PodCreate(ctx context.Context, opts entities.PodCreateOptions) (*entities.PodCreateReport, error) {
podSpec := specgen.NewPodSpecGenerator()
opts.ToPodSpecGen(podSpec)
diff --git a/test/e2e/pod_prune_test.go b/test/e2e/pod_prune_test.go
index 389d3cb27..d98383331 100644
--- a/test/e2e/pod_prune_test.go
+++ b/test/e2e/pod_prune_test.go
@@ -36,7 +36,7 @@ var _ = Describe("Podman pod prune", func() {
_, ec, _ := podmanTest.CreatePod("")
Expect(ec).To(Equal(0))
- result := podmanTest.Podman([]string{"pod", "prune"})
+ result := podmanTest.Podman([]string{"pod", "prune", "--force"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
})
@@ -49,7 +49,7 @@ var _ = Describe("Podman pod prune", func() {
ec2.WaitWithDefaultTimeout()
Expect(ec2.ExitCode()).To(Equal(0))
- result := podmanTest.Podman([]string{"pod", "prune"})
+ result := podmanTest.Podman([]string{"pod", "prune", "-f"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To((Equal(0)))
@@ -65,7 +65,7 @@ var _ = Describe("Podman pod prune", func() {
_, ec2, _ := podmanTest.RunLsContainerInPod("", podid)
Expect(ec2).To(Equal(0))
- result := podmanTest.Podman([]string{"pod", "prune"})
+ result := podmanTest.Podman([]string{"pod", "prune", "-f"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
@@ -73,21 +73,4 @@ var _ = Describe("Podman pod prune", func() {
result.WaitWithDefaultTimeout()
Expect(len(result.OutputToStringArray())).To(Equal(0))
})
-
- It("podman pod prune -f does remove a running container", func() {
- _, ec, podid := podmanTest.CreatePod("")
- Expect(ec).To(Equal(0))
-
- session := podmanTest.RunTopContainerInPod("", podid)
- session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Equal(0))
-
- result := podmanTest.Podman([]string{"pod", "prune", "-f"})
- result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Equal(0))
-
- result = podmanTest.Podman([]string{"ps", "-q"})
- result.WaitWithDefaultTimeout()
- Expect(result.OutputToString()).To(BeEmpty())
- })
})