diff options
-rw-r--r-- | cmd/podman/images.go | 28 | ||||
-rw-r--r-- | docs/podman-images.1.md | 16 | ||||
-rw-r--r-- | libpod/runtime.go | 5 | ||||
-rw-r--r-- | test/e2e/images_test.go | 26 | ||||
-rw-r--r-- | test/e2e/libpod_suite_test.go | 4 | ||||
-rw-r--r-- | test/e2e/run_entrypoint_test.go | 14 |
6 files changed, 77 insertions, 16 deletions
diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 7b906178d..654e59845 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/containers/storage" "github.com/docker/go-units" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" @@ -43,6 +44,7 @@ type imagesOptions struct { format string outputformat string sort string + all bool } // Type declaration and functions for sorting the images output @@ -178,6 +180,7 @@ func imagesCmd(c *cli.Context) error { digests: c.Bool("digests"), format: c.String("format"), sort: c.String("sort"), + all: c.Bool("all"), } opts.outputformat = opts.setOutputFormat() @@ -256,8 +259,14 @@ func sortImagesOutput(sortBy string, imagesOutput imagesSorted) imagesSorted { } // getImagesTemplateOutput returns the images information to be printed in human readable format -func getImagesTemplateOutput(ctx context.Context, runtime *libpod.Runtime, images []*image.Image, opts imagesOptions) (imagesOutput imagesSorted) { +func getImagesTemplateOutput(ctx context.Context, runtime *libpod.Runtime, images []*image.Image, opts imagesOptions, storageLayers []storage.Layer) (imagesOutput imagesSorted) { for _, img := range images { + // If all is false and the image doesn't have a name, check to see if the top layer of the image is a parent + // to another image's top layer. If it is, then it is an intermediate image so don't print out if the --all flag + // is not set. + if !opts.all && len(img.Names()) == 0 && !layerIsLeaf(storageLayers, img.TopLayer()) { + continue + } createdTime := img.Created() imageID := "sha256:" + img.ID() @@ -316,13 +325,17 @@ func generateImagesOutput(ctx context.Context, runtime *libpod.Runtime, images [ return nil } var out formats.Writer + storageLayers, err := runtime.GetLayers() + if err != nil { + return errors.Wrap(err, "error getting layers from store") + } switch opts.format { case formats.JSONString: imagesOutput := getImagesJSONOutput(ctx, runtime, images) out = formats.JSONStructArray{Output: imagesToGeneric([]imagesTemplateParams{}, imagesOutput)} default: - imagesOutput := getImagesTemplateOutput(ctx, runtime, images, opts) + imagesOutput := getImagesTemplateOutput(ctx, runtime, images, opts, storageLayers) out = formats.StdoutTemplateArray{Output: imagesToGeneric(imagesOutput, []imagesJSONParams{}), Template: opts.outputformat, Fields: imagesOutput[0].HeaderMap()} } return formats.Writer(out).Out() @@ -378,3 +391,14 @@ func CreateFilterFuncs(ctx context.Context, r *libpod.Runtime, c *cli.Context, i } return filterFuncs, nil } + +// layerIsLeaf goes through the layers in the store and checks if "layer" is +// the parent of any other layer in store. +func layerIsLeaf(storageLayers []storage.Layer, layer string) bool { + for _, storeLayer := range storageLayers { + if storeLayer.Parent == layer { + return false + } + } + return true +} diff --git a/docs/podman-images.1.md b/docs/podman-images.1.md index eb9712588..a97785de7 100644 --- a/docs/podman-images.1.md +++ b/docs/podman-images.1.md @@ -13,7 +13,7 @@ Displays locally stored images, their names, and their IDs. **--all, -a** -Show all images (by default filter out the intermediate image layers). The default is false. (This is a NOOP until podman build supports caching.) +Show all images (by default filter out the intermediate image layers). The default is false. **--digests** @@ -133,6 +133,20 @@ registry.access.redhat.com/rhel7 latest 7a840db7f020 2 weeks ago registry.fedoraproject.org/fedora 27 801894bc0e43 6 weeks ago 246MB ``` +``` +# podman images +REPOSITORY TAG IMAGE ID CREATED SIZE +localhost/test latest 18f0c080cd72 4 seconds ago 4.42MB +docker.io/library/alpine latest 3fd9065eaf02 5 months ago 4.41MB +# podman images -a +REPOSITORY TAG IMAGE ID CREATED SIZE +localhost/test latest 18f0c080cd72 6 seconds ago 4.42MB +<none> <none> 270e70dc54c0 7 seconds ago 4.42MB +<none> <none> 4ed6fbe43414 8 seconds ago 4.41MB +<none> <none> 6b0df8e71508 8 seconds ago 4.41MB +docker.io/library/alpine latest 3fd9065eaf02 5 months ago 4.41MB +``` + ## SEE ALSO podman(1) diff --git a/libpod/runtime.go b/libpod/runtime.go index 5d4b895cb..2584c091d 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -666,3 +666,8 @@ func SaveDefaultConfig(path string) error { func (r *Runtime) ImageRuntime() *image.Runtime { return r.imageRuntime } + +// GetLayers returns the layers available in the store +func (r *Runtime) GetLayers() ([]storage.Layer, error) { + return r.store.Layers() +} diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go index 5e30e95ec..c04ae91bd 100644 --- a/test/e2e/images_test.go +++ b/test/e2e/images_test.go @@ -100,7 +100,7 @@ var _ = Describe("Podman images", func() { It("podman images filter before image", func() { dockerfile := `FROM docker.io/library/alpine:latest ` - podmanTest.BuildImage(dockerfile, "foobar.com/before:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/before:latest", "false") result := podmanTest.Podman([]string{"images", "-q", "-f", "before=foobar.com/before:latest"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -114,7 +114,7 @@ var _ = Describe("Podman images", func() { dockerfile := `FROM docker.io/library/alpine:latest ` - podmanTest.BuildImage(dockerfile, "foobar.com/before:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/before:latest", "false") result := podmanTest.Podman([]string{"images", "-q", "-f", "after=docker.io/library/alpine:latest"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -124,8 +124,8 @@ var _ = Describe("Podman images", func() { It("podman images filter dangling", func() { dockerfile := `FROM docker.io/library/alpine:latest ` - podmanTest.BuildImage(dockerfile, "foobar.com/before:latest") - podmanTest.BuildImage(dockerfile, "foobar.com/before:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/before:latest", "false") + podmanTest.BuildImage(dockerfile, "foobar.com/before:latest", "false") result := podmanTest.Podman([]string{"images", "-q", "-f", "dangling=true"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -165,4 +165,22 @@ var _ = Describe("Podman images", func() { return size1 < size2 })).To(BeTrue()) }) + + It("podman images --all flag", func() { + dockerfile := `FROM docker.io/library/alpine:latest +RUN mkdir hello +RUN touch test.txt +ENV foo=bar +` + podmanTest.BuildImage(dockerfile, "test", "true") + session := podmanTest.Podman([]string{"images"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(Equal(4)) + + session2 := podmanTest.Podman([]string{"images", "--all"}) + session2.WaitWithDefaultTimeout() + Expect(session2.ExitCode()).To(Equal(0)) + Expect(len(session2.OutputToStringArray())).To(Equal(6)) + }) }) diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index d06818fd3..3d444f662 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -593,11 +593,11 @@ func (p *PodmanTest) GetContainerStatus() string { // BuildImage uses podman build and buildah to build an image // called imageName based on a string dockerfile -func (p *PodmanTest) BuildImage(dockerfile, imageName string) { +func (p *PodmanTest) BuildImage(dockerfile, imageName string, layers string) { dockerfilePath := filepath.Join(p.TempDir, "Dockerfile") err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755) Expect(err).To(BeNil()) - session := p.Podman([]string{"build", "-t", imageName, "--file", dockerfilePath, p.TempDir}) + session := p.Podman([]string{"build", "--layers=" + layers, "-t", imageName, "--file", dockerfilePath, p.TempDir}) session.Wait(120) Expect(session.ExitCode()).To(Equal(0)) } diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go index e06f8bb3a..7cae4e0df 100644 --- a/test/e2e/run_entrypoint_test.go +++ b/test/e2e/run_entrypoint_test.go @@ -33,7 +33,7 @@ var _ = Describe("Podman run entrypoint", func() { ENTRYPOINT [] CMD [] ` - podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(125)) @@ -43,7 +43,7 @@ CMD [] dockerfile := `FROM docker.io/library/alpine:latest ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] ` - podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -55,7 +55,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] CMD [ "-v"] ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] ` - podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -67,7 +67,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] CMD [ "-v"] ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] ` - podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest", "-i"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -78,7 +78,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] dockerfile := `FROM docker.io/library/alpine:latest ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] ` - podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest", "-i"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -90,7 +90,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] CMD ["-i"] ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] ` - podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "--entrypoint=uname", "foobar.com/entrypoint:latest"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -102,7 +102,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] CMD ["-i"] ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] ` - podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest") + podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "--entrypoint=uname", "foobar.com/entrypoint:latest", "-r"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) |