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 <bbaude@redhat.com>

MH: Removed dependence on remote-client adapter work to limit scale of changes

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
  • Loading branch information
baude authored and mheon committed Feb 8, 2019
1 parent cb3daec commit 5f4cdf1
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 40 deletions.
4 changes: 2 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,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 @@ -548,7 +548,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
26 changes: 15 additions & 11 deletions cmd/podman/images_prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"

"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/urfave/cli"
Expand All @@ -13,13 +14,19 @@ 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,
}
)

Expand All @@ -30,16 +37,13 @@ func pruneImagesCmd(c *cli.Context) error {
}
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.ImageRuntime().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 @@ -1017,7 +1017,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 @@ -2453,6 +2453,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
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 @@ -622,19 +622,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)
}
5 changes: 4 additions & 1 deletion test/e2e/prune_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,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 @@ -55,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 @@ -72,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 5f4cdf1

Please sign in to comment.