diff options
Diffstat (limited to 'cmd/podman')
-rw-r--r-- | cmd/podman/imagefilters/filters.go | 84 | ||||
-rw-r--r-- | cmd/podman/images.go | 56 | ||||
-rw-r--r-- | cmd/podman/images_prune.go | 15 | ||||
-rw-r--r-- | cmd/podman/shared/prune.go | 24 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 7 |
5 files changed, 131 insertions, 55 deletions
diff --git a/cmd/podman/imagefilters/filters.go b/cmd/podman/imagefilters/filters.go new file mode 100644 index 000000000..366510202 --- /dev/null +++ b/cmd/podman/imagefilters/filters.go @@ -0,0 +1,84 @@ +package imagefilters + +import ( + "context" + "strings" + "time" + + "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/inspect" +) + +// ResultFilter is a mock function for image filtering +type ResultFilter func(*adapter.ContainerImage) bool + +// Filter is a function to determine whether an image is included in +// command output. Images to be outputted are tested using the function. A true +// return will include the image, a false return will exclude it. +type Filter func(*adapter.ContainerImage, *inspect.ImageData) bool + +// CreatedBeforeFilter allows you to filter on images created before +// the given time.Time +func CreatedBeforeFilter(createTime time.Time) ResultFilter { + return func(i *adapter.ContainerImage) bool { + return i.Created().Before(createTime) + } +} + +// CreatedAfterFilter allows you to filter on images created after +// the given time.Time +func CreatedAfterFilter(createTime time.Time) ResultFilter { + return func(i *adapter.ContainerImage) bool { + return i.Created().After(createTime) + } +} + +// DanglingFilter allows you to filter images for dangling images +func DanglingFilter() ResultFilter { + return func(i *adapter.ContainerImage) bool { + return i.Dangling() + } +} + +// 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 + return func(i *adapter.ContainerImage) bool { + var value string + splitFilter := strings.Split(labelfilter, "=") + key := splitFilter[0] + if len(splitFilter) > 1 { + value = splitFilter[1] + } + labels, err := i.Labels(ctx) + if err != nil { + return false + } + if len(strings.TrimSpace(labels[key])) > 0 && len(strings.TrimSpace(value)) == 0 { + return true + } + return labels[key] == value + } +} + +// OutputImageFilter allows you to filter by an a specific image name +func OutputImageFilter(userImage *adapter.ContainerImage) ResultFilter { + return func(i *adapter.ContainerImage) bool { + return userImage.ID() == i.ID() + } +} + +// FilterImages filters images using a set of predefined filter funcs +func FilterImages(images []*adapter.ContainerImage, filters []ResultFilter) []*adapter.ContainerImage { + var filteredImages []*adapter.ContainerImage + for _, image := range images { + include := true + for _, filter := range filters { + include = include && filter(image) + } + if include { + filteredImages = append(filteredImages, image) + } + } + return filteredImages +} diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 522863b1b..8b8ce78bd 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -2,6 +2,8 @@ package main import ( "context" + "github.com/containers/libpod/cmd/podman/imagefilters" + "github.com/containers/libpod/libpod/adapter" "reflect" "sort" "strings" @@ -9,11 +11,9 @@ import ( "unicode" "github.com/containers/libpod/cmd/podman/formats" - "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" "github.com/docker/go-units" - digest "github.com/opencontainers/go-digest" + "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -145,20 +145,20 @@ var ( func imagesCmd(c *cli.Context) error { var ( - filterFuncs []image.ResultFilter - newImage *image.Image + filterFuncs []imagefilters.ResultFilter + newImage *adapter.ContainerImage ) if err := validateFlags(c, imagesFlags); err != nil { return err } - runtime, err := libpodruntime.GetRuntime(c) + localRuntime, err := adapter.GetRuntime(c) if err != nil { return errors.Wrapf(err, "Could not get runtime") } - defer runtime.Shutdown(false) + defer localRuntime.Runtime.Shutdown(false) if len(c.Args()) == 1 { - newImage, err = runtime.ImageRuntime().NewFromLocal(c.Args().Get(0)) + newImage, err = localRuntime.NewImageFromLocal(c.Args().Get(0)) if err != nil { return err } @@ -171,7 +171,7 @@ func imagesCmd(c *cli.Context) error { ctx := getContext() if len(c.StringSlice("filter")) > 0 || newImage != nil { - filterFuncs, err = CreateFilterFuncs(ctx, runtime, c, newImage) + filterFuncs, err = CreateFilterFuncs(ctx, localRuntime, c, newImage) if err != nil { return err } @@ -195,20 +195,20 @@ func imagesCmd(c *cli.Context) error { children to the image once built. until buildah supports caching builds, it will not generate these intermediate images. */ - images, err := runtime.ImageRuntime().GetImages() + images, err := localRuntime.GetImages() if err != nil { return errors.Wrapf(err, "unable to get images") } - var filteredImages []*image.Image - // filter the images + var filteredImages []*adapter.ContainerImage + //filter the images if len(c.StringSlice("filter")) > 0 || newImage != nil { - filteredImages = image.FilterImages(images, filterFuncs) + filteredImages = imagefilters.FilterImages(images, filterFuncs) } else { filteredImages = images } - return generateImagesOutput(ctx, runtime, filteredImages, opts) + return generateImagesOutput(ctx, filteredImages, opts) } func (i imagesOptions) setOutputFormat() string { @@ -263,7 +263,7 @@ 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, images []*adapter.ContainerImage, opts imagesOptions) (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 @@ -319,7 +319,7 @@ func getImagesTemplateOutput(ctx context.Context, runtime *libpod.Runtime, image } // getImagesJSONOutput returns the images information in its raw form -func getImagesJSONOutput(ctx context.Context, runtime *libpod.Runtime, images []*image.Image) (imagesOutput []imagesJSONParams) { +func getImagesJSONOutput(ctx context.Context, images []*adapter.ContainerImage) (imagesOutput []imagesJSONParams) { for _, img := range images { size, err := img.Size(ctx) if err != nil { @@ -339,7 +339,7 @@ func getImagesJSONOutput(ctx context.Context, runtime *libpod.Runtime, images [] // generateImagesOutput generates the images based on the format provided -func generateImagesOutput(ctx context.Context, runtime *libpod.Runtime, images []*image.Image, opts imagesOptions) error { +func generateImagesOutput(ctx context.Context, images []*adapter.ContainerImage, opts imagesOptions) error { if len(images) == 0 { return nil } @@ -347,10 +347,10 @@ func generateImagesOutput(ctx context.Context, runtime *libpod.Runtime, images [ switch opts.format { case formats.JSONString: - imagesOutput := getImagesJSONOutput(ctx, runtime, images) + imagesOutput := getImagesJSONOutput(ctx, images) out = formats.JSONStructArray{Output: imagesToGeneric([]imagesTemplateParams{}, imagesOutput)} default: - imagesOutput := getImagesTemplateOutput(ctx, runtime, images, opts) + imagesOutput := getImagesTemplateOutput(ctx, images, opts) out = formats.StdoutTemplateArray{Output: imagesToGeneric(imagesOutput, []imagesJSONParams{}), Template: opts.outputformat, Fields: imagesOutput[0].HeaderMap()} } return formats.Writer(out).Out() @@ -375,34 +375,34 @@ func (i *imagesTemplateParams) HeaderMap() map[string]string { // CreateFilterFuncs returns an array of filter functions based on the user inputs // and is later used to filter images for output -func CreateFilterFuncs(ctx context.Context, r *libpod.Runtime, c *cli.Context, img *image.Image) ([]image.ResultFilter, error) { - var filterFuncs []image.ResultFilter +func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, c *cli.Context, img *adapter.ContainerImage) ([]imagefilters.ResultFilter, error) { + var filterFuncs []imagefilters.ResultFilter for _, filter := range c.StringSlice("filter") { splitFilter := strings.Split(filter, "=") switch splitFilter[0] { case "before": - before, err := r.ImageRuntime().NewFromLocal(splitFilter[1]) + before, err := r.NewImageFromLocal(splitFilter[1]) if err != nil { return nil, errors.Wrapf(err, "unable to find image %s in local stores", splitFilter[1]) } - filterFuncs = append(filterFuncs, image.CreatedBeforeFilter(before.Created())) + filterFuncs = append(filterFuncs, imagefilters.CreatedBeforeFilter(before.Created())) case "after": - after, err := r.ImageRuntime().NewFromLocal(splitFilter[1]) + after, err := r.NewImageFromLocal(splitFilter[1]) if err != nil { return nil, errors.Wrapf(err, "unable to find image %s in local stores", splitFilter[1]) } - filterFuncs = append(filterFuncs, image.CreatedAfterFilter(after.Created())) + filterFuncs = append(filterFuncs, imagefilters.CreatedAfterFilter(after.Created())) case "dangling": - filterFuncs = append(filterFuncs, image.DanglingFilter()) + filterFuncs = append(filterFuncs, imagefilters.DanglingFilter()) case "label": labelFilter := strings.Join(splitFilter[1:], "=") - filterFuncs = append(filterFuncs, image.LabelFilter(ctx, labelFilter)) + filterFuncs = append(filterFuncs, imagefilters.LabelFilter(ctx, labelFilter)) default: return nil, errors.Errorf("invalid filter %s ", splitFilter[0]) } } if img != nil { - filterFuncs = append(filterFuncs, image.OutputImageFilter(img)) + filterFuncs = append(filterFuncs, imagefilters.OutputImageFilter(img)) } return filterFuncs, nil } diff --git a/cmd/podman/images_prune.go b/cmd/podman/images_prune.go index cb72a498f..06879e02d 100644 --- a/cmd/podman/images_prune.go +++ b/cmd/podman/images_prune.go @@ -1,8 +1,8 @@ package main import ( + "fmt" "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/cmd/podman/shared" "github.com/pkg/errors" "github.com/urfave/cli" ) @@ -30,5 +30,16 @@ func pruneImagesCmd(c *cli.Context) error { } defer runtime.Shutdown(false) - return shared.Prune(runtime.ImageRuntime()) + 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()) + } + fmt.Println(i.ID()) + } + return nil } diff --git a/cmd/podman/shared/prune.go b/cmd/podman/shared/prune.go deleted file mode 100644 index 90cfe4475..000000000 --- a/cmd/podman/shared/prune.go +++ /dev/null @@ -1,24 +0,0 @@ -package shared - -import ( - "fmt" - "github.com/pkg/errors" - - "github.com/containers/libpod/libpod/image" -) - -// Prune removes all unnamed and unused images from the local store -func Prune(ir *image.Runtime) error { - pruneImages, err := ir.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()) - } - fmt.Println(i.ID()) - } - return nil -} diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 4e8b69faf..a3e8c050e 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -37,7 +37,8 @@ type ImageInList ( size: int, virtualSize: int, containers: int, - labels: [string]string + labels: [string]string, + isParent: bool ) # ImageHistory describes the returned structure from ImageHistory. @@ -1015,6 +1016,10 @@ method MountContainer(name: string) -> (path: string) # ~~~ 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) + # This function is not implemented yet. method ListContainerPorts(name: string) -> (notimplemented: NotImplemented) |