Skip to content

Commit

Permalink
podman image prune -- implement all flag
Browse files Browse the repository at this point in the history
we now, by default, only prune dangling images.  if --all is passed, we
prune dangling images AND images that do not have an associated containers.

also went ahead and enabled the podman-remote image prune side of things.

Fixes: containers#2192

Signed-off-by: baude <[email protected]>
  • Loading branch information
baude committed Jan 29, 2019
1 parent ad5579e commit 656033c
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 44 deletions.
4 changes: 2 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in

[func ImageExists(name: string) int](#ImageExists)

[func ImagesPrune() []string](#ImagesPrune)
[func ImagesPrune(all: bool) []string](#ImagesPrune)

[func ImportImage(source: string, reference: string, message: string, changes: []string) string](#ImportImage)

Expand Down Expand Up @@ -580,7 +580,7 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.ImageExists '{"name": "im
### <a name="ImagesPrune"></a>func ImagesPrune
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">

method ImagesPrune() [[]string](#[]string)</div>
method ImagesPrune(all: [bool](https://godoc.org/builtin#bool)) [[]string](#[]string)</div>
ImagesPrune removes all unused images from the local store. Upon successful pruning,
the IDs of the removed images are returned.
### <a name="ImportImage"></a>func ImportImage
Expand Down
29 changes: 16 additions & 13 deletions cmd/podman/images_prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
Expand All @@ -13,33 +13,36 @@ var (
Removes all unnamed images from local storage
`

pruneImageFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "remove all unused images, not just dangling ones",
},
}
pruneImagesCommand = cli.Command{
Name: "prune",
Usage: "Remove unused images",
Description: pruneImagesDescription,
Action: pruneImagesCmd,
OnUsageError: usageErrorHandler,
Flags: pruneImageFlags,
}
)

func pruneImagesCmd(c *cli.Context) error {
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := adapter.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)

pruneImages, err := runtime.ImageRuntime().GetPruneImages()
if err != nil {
return err
}

for _, i := range pruneImages {
if err := i.Remove(true); err != nil {
return errors.Wrapf(err, "failed to remove %s", i.ID())
// Call prune; if any cids are returned, print them and then
// return err in case an error also came up
pruneCids, err := runtime.PruneImages(c.Bool("all"))
if len(pruneCids) > 0 {
for _, cid := range pruneCids {
fmt.Println(cid)
}
fmt.Println(i.ID())
}
return nil
return err
}
2 changes: 1 addition & 1 deletion cmd/podman/varlink/io.podman.varlink
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,7 @@ method UnmountContainer(name: string, force: bool) -> ()

# ImagesPrune removes all unused images from the local store. Upon successful pruning,
# the IDs of the removed images are returned.
method ImagesPrune() -> (pruned: []string)
method ImagesPrune(all: bool) -> (pruned: []string)

# This function is not implemented yet.
method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
Expand Down
2 changes: 2 additions & 0 deletions completions/bash/podman
Original file line number Diff line number Diff line change
Expand Up @@ -2459,6 +2459,8 @@ _podman_images_prune() {
"

local boolean_options="
-a
--all
-h
--help
"
Expand Down
21 changes: 18 additions & 3 deletions docs/podman-image-prune.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,38 @@ podman-image-prune - Remove all unused images

# SYNOPSIS
**podman image prune**
[**-a**|**--all**]
[**-h**|**--help**]

# DESCRIPTION
**podman image prune** removes all unused images from local storage. An unused image
is defined as an image that does not have any containers based on it.
**podman image prune** removes all dangling images from local storage. With the `all` option,
you can delete all unused images. Unused images are dangling images as well as any image that
does not have any containers based on it.

## OPTIONS
**--all, -a**

Remove dangling images and images that have no associated containers.

## Examples ##

Remove all unused images from local storage
Remove all dangling images from local storage
```
$ sudo podman image prune
f3e20dc537fb04cb51672a5cb6fdf2292e61d411315549391a0d1f64e4e3097e
324a7a3b2e0135f4226ffdd473e4099fd9e477a74230cdc35de69e84c0f9d907
```

Remove all unused images from local storage
```
$ sudo podman image prune -a
f3e20dc537fb04cb51672a5cb6fdf2292e61d411315549391a0d1f64e4e3097e
324a7a3b2e0135f4226ffdd473e4099fd9e477a74230cdc35de69e84c0f9d907
6125002719feb1ddf3030acab1df6156da7ce0e78e571e9b6e9c250424d6220c
91e732da5657264c6f4641b8d0c4001c218ae6c1adb9dcef33ad00cafd37d8b6
e4e5109420323221f170627c138817770fb64832da7d8fe2babd863148287fca
77a57fa8285e9656dbb7b23d9efa837a106957409ddd702f995605af27a45ebe
```

## SEE ALSO
Expand Down
5 changes: 5 additions & 0 deletions libpod/adapter/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,8 @@ func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) {
}
return &Container{ctr}, nil
}

// PruneImages is wrapper into PruneImages within the image pkg
func (r *LocalRuntime) PruneImages(all bool) ([]string, error) {
return r.ImageRuntime().PruneImages(all)
}
3 changes: 3 additions & 0 deletions libpod/adapter/runtime_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,6 @@ func (r *LocalRuntime) Config(name string) *libpod.ContainerConfig {
return &data

}
func (r *LocalRuntime) PruneImages(all bool) ([]string, error) {
return iopodman.ImagesPrune().Call(r.Conn, all)
}
39 changes: 30 additions & 9 deletions libpod/image/prune.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
package image

import "github.com/pkg/errors"

// GetPruneImages returns a slice of images that have no names/unused
func (ir *Runtime) GetPruneImages() ([]*Image, error) {
func (ir *Runtime) GetPruneImages(all bool) ([]*Image, error) {
var (
unamedImages []*Image
pruneImages []*Image
)
allImages, err := ir.GetImages()
if err != nil {
return nil, err
}
for _, i := range allImages {
if len(i.Names()) == 0 {
unamedImages = append(unamedImages, i)
pruneImages = append(pruneImages, i)
continue
}
containers, err := i.Containers()
if err != nil {
return nil, err
if all {
containers, err := i.Containers()
if err != nil {
return nil, err
}
if len(containers) < 1 {
pruneImages = append(pruneImages, i)
}
}
if len(containers) < 1 {
unamedImages = append(unamedImages, i)
}
return pruneImages, nil
}

// PruneImages prunes dangling and optionally all unused images from the local
// image store
func (ir *Runtime) PruneImages(all bool) ([]string, error) {
var prunedCids []string
pruneImages, err := ir.GetPruneImages(all)
if err != nil {
return nil, errors.Wrap(err, "unable to get images to prune")
}
for _, p := range pruneImages {
if err := p.Remove(true); err != nil {
return nil, errors.Wrap(err, "failed to prune image")
}
prunedCids = append(prunedCids, p.ID())
}
return unamedImages, nil
return prunedCids, nil
}
17 changes: 4 additions & 13 deletions pkg/varlinkapi/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,19 +627,10 @@ func (i *LibpodAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman.
}

// ImagesPrune ....
func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall) error {
var (
pruned []string
)
pruneImages, err := i.Runtime.ImageRuntime().GetPruneImages()
func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall, all bool) error {
prunedImages, err := i.Runtime.ImageRuntime().PruneImages(all)
if err != nil {
return err
}
for _, i := range pruneImages {
if err := i.Remove(true); err != nil {
return call.ReplyErrorOccurred(err.Error())
}
pruned = append(pruned, i.ID())
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyImagesPrune(pruned)
return call.ReplyImagesPrune(prunedImages)
}
7 changes: 4 additions & 3 deletions test/e2e/prune_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// +build !remoteclient

package integration

import (
Expand Down Expand Up @@ -41,6 +39,7 @@ var _ = Describe("Podman rm", func() {
})

It("podman container prune containers", func() {
SkipIfRemote()
top := podmanTest.RunTopContainer("")
top.WaitWithDefaultTimeout()
Expect(top.ExitCode()).To(Equal(0))
Expand All @@ -57,6 +56,7 @@ var _ = Describe("Podman rm", func() {
})

It("podman image prune none images", func() {
SkipIfRemote()
podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")

none := podmanTest.Podman([]string{"images", "-a"})
Expand All @@ -74,10 +74,11 @@ var _ = Describe("Podman rm", func() {
Expect(none.ExitCode()).To(Equal(0))
hasNoneAfter, _ := after.GrepString("<none>")
Expect(hasNoneAfter).To(BeFalse())
Expect(len(after.OutputToStringArray()) > 1).To(BeTrue())
})

It("podman image prune unused images", func() {
prune := podmanTest.Podman([]string{"image", "prune"})
prune := podmanTest.Podman([]string{"image", "prune", "-a"})
prune.WaitWithDefaultTimeout()
Expect(prune.ExitCode()).To(Equal(0))

Expand Down

0 comments on commit 656033c

Please sign in to comment.