aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-04-17 15:19:45 -0400
committerGitHub <noreply@github.com>2020-04-17 15:19:45 -0400
commitbd8a0b08cdea5f15d6033b24038ba71aef1f8962 (patch)
tree581e283021a0edff9dfd89be73ddd7ccceb42b1d
parentba289dcd79e3a2b5ec5dc02bd8adb84c93bef577 (diff)
parentd8321363498c349647409dea1b6e15f8cf0ac17a (diff)
downloadpodman-bd8a0b08cdea5f15d6033b24038ba71aef1f8962.tar.gz
podman-bd8a0b08cdea5f15d6033b24038ba71aef1f8962.tar.bz2
podman-bd8a0b08cdea5f15d6033b24038ba71aef1f8962.zip
Merge pull request #5548 from kunalkushwaha/image-prune
image prune skips images with child images.
-rw-r--r--docs/source/markdown/podman-image-prune.1.md2
-rw-r--r--libpod/image/image.go24
-rw-r--r--libpod/image/prune.go22
-rw-r--r--test/e2e/prune_test.go29
4 files changed, 67 insertions, 10 deletions
diff --git a/docs/source/markdown/podman-image-prune.1.md b/docs/source/markdown/podman-image-prune.1.md
index c76e9bd3f..cf9e50366 100644
--- a/docs/source/markdown/podman-image-prune.1.md
+++ b/docs/source/markdown/podman-image-prune.1.md
@@ -11,6 +11,8 @@ podman-image-prune - Remove all unused images from the local store
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.
+The image prune command does not prune cache images that only use layers that are necessary for other images.
+
## OPTIONS
**--all**, **-a**
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 80cc6f15a..7198a42a3 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -32,10 +32,10 @@ import (
"github.com/containers/libpod/pkg/registries"
"github.com/containers/libpod/pkg/util"
"github.com/containers/storage"
- "github.com/opencontainers/go-digest"
+ digest "github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
- "github.com/opentracing/opentracing-go"
+ opentracing "github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -847,6 +847,26 @@ func (i *Image) Dangling() bool {
return len(i.Names()) == 0
}
+// Intermediate returns true if the image is cache or intermediate image.
+// Cache image has parent and child.
+func (i *Image) Intermediate(ctx context.Context) (bool, error) {
+ parent, err := i.IsParent(ctx)
+ if err != nil {
+ return false, err
+ }
+ if !parent {
+ return false, nil
+ }
+ img, err := i.GetParent(ctx)
+ if err != nil {
+ return false, err
+ }
+ if img != nil {
+ return true, nil
+ }
+ return false, nil
+}
+
// Labels returns the image's labels
func (i *Image) Labels(ctx context.Context) (map[string]string, error) {
imgInspect, err := i.imageInspectInfo(ctx)
diff --git a/libpod/image/prune.go b/libpod/image/prune.go
index 3afff22af..3b4ea74c4 100644
--- a/libpod/image/prune.go
+++ b/libpod/image/prune.go
@@ -57,7 +57,7 @@ func generatePruneFilterFuncs(filter, filterValue string) (ImageFilter, error) {
}
// GetPruneImages returns a slice of images that have no names/unused
-func (ir *Runtime) GetPruneImages(all bool, filterFuncs []ImageFilter) ([]*Image, error) {
+func (ir *Runtime) GetPruneImages(ctx context.Context, all bool, filterFuncs []ImageFilter) ([]*Image, error) {
var (
pruneImages []*Image
)
@@ -74,10 +74,6 @@ func (ir *Runtime) GetPruneImages(all bool, filterFuncs []ImageFilter) ([]*Image
}
}
- if len(i.Names()) == 0 {
- pruneImages = append(pruneImages, i)
- continue
- }
if all {
containers, err := i.Containers()
if err != nil {
@@ -85,8 +81,22 @@ func (ir *Runtime) GetPruneImages(all bool, filterFuncs []ImageFilter) ([]*Image
}
if len(containers) < 1 {
pruneImages = append(pruneImages, i)
+ continue
}
}
+
+ //skip the cache or intermediate images
+ intermediate, err := i.Intermediate(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if intermediate {
+ continue
+ }
+
+ if i.Dangling() {
+ pruneImages = append(pruneImages, i)
+ }
}
return pruneImages, nil
}
@@ -111,7 +121,7 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
filterFuncs = append(filterFuncs, generatedFunc)
}
- pruneImages, err := ir.GetPruneImages(all, filterFuncs)
+ pruneImages, err := ir.GetPruneImages(ctx, all, filterFuncs)
if err != nil {
return nil, errors.Wrap(err, "unable to get images to prune")
}
diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go
index 672b0e103..83a8d3b18 100644
--- a/test/e2e/prune_test.go
+++ b/test/e2e/prune_test.go
@@ -87,7 +87,7 @@ var _ = Describe("Podman prune", func() {
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
})
- It("podman image prune none images", func() {
+ It("podman image prune skip cache images", func() {
SkipIfRemote()
podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")
@@ -105,10 +105,35 @@ var _ = Describe("Podman prune", func() {
after.WaitWithDefaultTimeout()
Expect(none.ExitCode()).To(Equal(0))
hasNoneAfter, _ := after.GrepString("<none>")
- Expect(hasNoneAfter).To(BeFalse())
+ Expect(hasNoneAfter).To(BeTrue())
Expect(len(after.OutputToStringArray()) > 1).To(BeTrue())
})
+ It("podman image prune dangling images", func() {
+ SkipIfRemote()
+ podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")
+ podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")
+
+ none := podmanTest.Podman([]string{"images", "-a"})
+ none.WaitWithDefaultTimeout()
+ Expect(none.ExitCode()).To(Equal(0))
+ hasNone, result := none.GrepString("<none>")
+ Expect(len(result)).To(Equal(2))
+ Expect(hasNone).To(BeTrue())
+
+ prune := podmanTest.Podman([]string{"image", "prune", "-f"})
+ prune.WaitWithDefaultTimeout()
+ Expect(prune.ExitCode()).To(Equal(0))
+
+ after := podmanTest.Podman([]string{"images", "-a"})
+ after.WaitWithDefaultTimeout()
+ Expect(none.ExitCode()).To(Equal(0))
+ hasNoneAfter, result := none.GrepString("<none>")
+ Expect(hasNoneAfter).To(BeTrue())
+ Expect(len(after.OutputToStringArray()) > 1).To(BeTrue())
+ Expect(len(result) > 0).To(BeTrue())
+ })
+
It("podman image prune unused images", func() {
podmanTest.RestoreAllArtifacts()
prune := podmanTest.PodmanNoCache([]string{"image", "prune", "-af"})