From 8ae97b2f57a845dd05f70f244a763c53250b4e81 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Wed, 17 Jul 2019 10:49:03 -0400 Subject: Add support for listing read/only and read/write images When removing --all images prune images only attempt to remove read/write images, ignore read/only images Signed-off-by: Daniel J Walsh --- cmd/podman/imagefilters/filters.go | 10 +++++++++ cmd/podman/images.go | 43 +++++++++++++++++++++++++++--------- cmd/podman/rmi.go | 4 ++-- cmd/podman/varlink/io.podman.varlink | 3 ++- 4 files changed, 47 insertions(+), 13 deletions(-) (limited to 'cmd') diff --git a/cmd/podman/imagefilters/filters.go b/cmd/podman/imagefilters/filters.go index aa5776599..0b08314ce 100644 --- a/cmd/podman/imagefilters/filters.go +++ b/cmd/podman/imagefilters/filters.go @@ -46,6 +46,16 @@ func DanglingFilter(danglingImages bool) ResultFilter { } } +// ReadOnlyFilter allows you to filter images based on read/only and read/write +func ReadOnlyFilter(readOnly bool) ResultFilter { + return func(i *adapter.ContainerImage) bool { + if readOnly { + return i.IsReadOnly() + } + return !i.IsReadOnly() + } +} + // LabelFilter allows you to filter by images labels key and/or value func LabelFilter(ctx context.Context, labelfilter string) ResultFilter { // We need to handle both label=key and label=key=value diff --git a/cmd/podman/images.go b/cmd/podman/images.go index f842573d9..281d93e71 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -30,14 +30,16 @@ type imagesTemplateParams struct { Created string CreatedTime time.Time Size string + ReadOnly bool } type imagesJSONParams struct { - ID string `json:"id"` - Name []string `json:"names"` - Digest digest.Digest `json:"digest"` - Created time.Time `json:"created"` - Size *uint64 `json:"size"` + ID string `json:"id"` + Name []string `json:"names"` + Digest digest.Digest `json:"digest"` + Created time.Time `json:"created"` + Size *uint64 `json:"size"` + ReadOnly bool `json:"readonly"` } type imagesOptions struct { @@ -49,6 +51,7 @@ type imagesOptions struct { outputformat string sort string all bool + useReadOnly bool } // Type declaration and functions for sorting the images output @@ -175,6 +178,13 @@ func imagesCmd(c *cliconfig.ImagesValues) error { return errors.Wrapf(err, "unable to get images") } + for _, image := range images { + if image.IsReadOnly() { + opts.outputformat += "{{.ReadOnly}}\t" + break + } + } + var filteredImages []*adapter.ContainerImage //filter the images if len(c.Filter) > 0 || len(c.InputArgs) == 1 { @@ -282,6 +292,7 @@ func getImagesTemplateOutput(ctx context.Context, images []*adapter.ContainerIma CreatedTime: createdTime, Created: units.HumanDuration(time.Since(createdTime)) + " ago", Size: sizeStr, + ReadOnly: img.IsReadOnly(), } imagesOutput = append(imagesOutput, params) if opts.quiet { // Show only one image ID when quiet @@ -305,11 +316,12 @@ func getImagesJSONOutput(ctx context.Context, images []*adapter.ContainerImage) size = nil } params := imagesJSONParams{ - ID: img.ID(), - Name: img.Names(), - Digest: img.Digest(), - Created: img.Created(), - Size: size, + ID: img.ID(), + Name: img.Names(), + Digest: img.Digest(), + Created: img.Created(), + Size: size, + ReadOnly: img.IsReadOnly(), } imagesOutput = append(imagesOutput, params) } @@ -351,6 +363,11 @@ func GenImageOutputMap() map[string]string { if value == "ID" { value = "Image" + value } + + if value == "ReadOnly" { + values[key] = "R/O" + continue + } values[key] = strings.ToUpper(splitCamelCase(value)) } return values @@ -378,6 +395,12 @@ func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, filters []s return nil, errors.Wrapf(err, "unable to find image %s in local stores", splitFilter[1]) } filterFuncs = append(filterFuncs, imagefilters.CreatedAfterFilter(after.Created())) + case "readonly": + readonly, err := strconv.ParseBool(splitFilter[1]) + if err != nil { + return nil, errors.Wrapf(err, "invalid filter readonly=%s", splitFilter[1]) + } + filterFuncs = append(filterFuncs, imagefilters.ReadOnlyFilter(readonly)) case "dangling": danglingImages, err := strconv.ParseBool(splitFilter[1]) if err != nil { diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go index 9229d497e..57e78c34a 100644 --- a/cmd/podman/rmi.go +++ b/cmd/podman/rmi.go @@ -87,7 +87,7 @@ func rmiCmd(c *cliconfig.RmiValues) error { if removeAll { var imagesToDelete []*adapter.ContainerImage - imagesToDelete, err = runtime.GetImages() + imagesToDelete, err = runtime.GetRWImages() if err != nil { return errors.Wrapf(err, "unable to query local images") } @@ -107,7 +107,7 @@ func rmiCmd(c *cliconfig.RmiValues) error { removeImage(i) } lastNumberofImages = len(imagesToDelete) - imagesToDelete, err = runtime.GetImages() + imagesToDelete, err = runtime.GetRWImages() if err != nil { return err } diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 0bf236b77..72b15c328 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -69,7 +69,8 @@ type Image ( containers: int, labels: [string]string, isParent: bool, - topLayer: string + topLayer: string, + readOnly: bool ) # ImageHistory describes the returned structure from ImageHistory. -- cgit v1.2.3-54-g00ecf