From 8be7b466d86b53d170f82a4bd94667c4db71db59 Mon Sep 17 00:00:00 2001 From: baude Date: Mon, 9 Dec 2019 12:35:57 -0600 Subject: move image filters under libpod/images to make things more effecient for the api work we are doing, we should process image filters internally (as opposed to in main). this allows for better api responses and more closely affiliated functions. Signed-off-by: baude --- cmd/podman/imagefilters/filters.go | 121 ----------------------------------- cmd/podman/images.go | 81 ++--------------------- cmd/podman/varlink/io.podman.varlink | 5 ++ 3 files changed, 12 insertions(+), 195 deletions(-) delete mode 100644 cmd/podman/imagefilters/filters.go (limited to 'cmd') diff --git a/cmd/podman/imagefilters/filters.go b/cmd/podman/imagefilters/filters.go deleted file mode 100644 index 0b08314ce..000000000 --- a/cmd/podman/imagefilters/filters.go +++ /dev/null @@ -1,121 +0,0 @@ -package imagefilters - -import ( - "context" - "fmt" - "path/filepath" - "strings" - "time" - - "github.com/containers/libpod/pkg/adapter" - "github.com/containers/libpod/pkg/inspect" - "github.com/sirupsen/logrus" -) - -// 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(danglingImages bool) ResultFilter { - return func(i *adapter.ContainerImage) bool { - if danglingImages { - return i.Dangling() - } - return !i.Dangling() - } -} - -// 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 - 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 - } -} - -// ReferenceFilter allows you to filter by image name -// Replacing all '/' with '|' so that filepath.Match() can work -// '|' character is not valid in image name, so this is safe -func ReferenceFilter(ctx context.Context, referenceFilter string) ResultFilter { - filter := fmt.Sprintf("*%s*", referenceFilter) - filter = strings.Replace(filter, "/", "|", -1) - return func(i *adapter.ContainerImage) bool { - for _, name := range i.Names() { - newName := strings.Replace(name, "/", "|", -1) - match, err := filepath.Match(filter, newName) - if err != nil { - logrus.Errorf("failed to match %s and %s, %q", name, referenceFilter, err) - } - if match { - return true - } - } - return false - } -} - -// 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 6b16272f4..e42546a55 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -5,14 +5,12 @@ import ( "fmt" "reflect" "sort" - "strconv" "strings" "time" "unicode" "github.com/containers/buildah/pkg/formats" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/imagefilters" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/adapter" "github.com/docker/go-units" @@ -138,10 +136,10 @@ func init() { func imagesCmd(c *cliconfig.ImagesValues) error { var ( - filterFuncs []imagefilters.ResultFilter - image string + image string ) + ctx := getContext() runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "Could not get runtime") @@ -156,15 +154,9 @@ func imagesCmd(c *cliconfig.ImagesValues) error { if len(c.Filter) > 0 && image != "" { return errors.New("can not specify an image and a filter") } - ctx := getContext() - - if len(c.Filter) > 0 { - filterFuncs, err = CreateFilterFuncs(ctx, runtime, c.Filter, nil) - } else { - filterFuncs, err = CreateFilterFuncs(ctx, runtime, []string{fmt.Sprintf("reference=%s", image)}, nil) - } - if err != nil { - return err + filters := c.Filter + if len(filters) < 1 { + filters = append(filters, fmt.Sprintf("reference=%s", image)) } opts := imagesOptions{ @@ -179,26 +171,17 @@ func imagesCmd(c *cliconfig.ImagesValues) error { } opts.outputformat = opts.setOutputFormat() - images, err := runtime.GetImages() + filteredImages, err := runtime.GetFilteredImages(filters, false) if err != nil { return errors.Wrapf(err, "unable to get images") } - for _, image := range images { + for _, image := range filteredImages { if image.IsReadOnly() { opts.outputformat += "{{.ReadOnly}}\t" break } } - - var filteredImages []*adapter.ContainerImage - //filter the images - if len(c.Filter) > 0 || len(c.InputArgs) == 1 { - filteredImages = imagefilters.FilterImages(images, filterFuncs) - } else { - filteredImages = images - } - return generateImagesOutput(ctx, filteredImages, opts) } @@ -392,53 +375,3 @@ func GenImageOutputMap() map[string]string { } return values } - -// 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 *adapter.LocalRuntime, filters []string, img *adapter.ContainerImage) ([]imagefilters.ResultFilter, error) { - var filterFuncs []imagefilters.ResultFilter - for _, filter := range filters { - splitFilter := strings.Split(filter, "=") - if len(splitFilter) < 2 { - return nil, errors.Errorf("invalid filter syntax %s", filter) - } - switch splitFilter[0] { - case "before": - 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, imagefilters.CreatedBeforeFilter(before.Created())) - case "after": - 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, 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 { - return nil, errors.Wrapf(err, "invalid filter dangling=%s", splitFilter[1]) - } - filterFuncs = append(filterFuncs, imagefilters.DanglingFilter(danglingImages)) - case "label": - labelFilter := strings.Join(splitFilter[1:], "=") - filterFuncs = append(filterFuncs, imagefilters.LabelFilter(ctx, labelFilter)) - case "reference": - referenceFilter := strings.Join(splitFilter[1:], "=") - filterFuncs = append(filterFuncs, imagefilters.ReferenceFilter(ctx, referenceFilter)) - default: - return nil, errors.Errorf("invalid filter %s ", splitFilter[0]) - } - } - if img != nil { - filterFuncs = append(filterFuncs, imagefilters.OutputImageFilter(img)) - } - return filterFuncs, nil -} diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index a3fd27ed6..2251050c3 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -784,6 +784,11 @@ method DeleteStoppedContainers() -> (containers: []string) # See also [InspectImage](#InspectImage). method ListImages() -> (images: []Image) +# ListImagesWithFilters returns information about the images that are currently in storage +# after one or more filters has been applied. +# See also [InspectImage](#InspectImage). +method ListImagesWithFilters(filters: []string) -> (images: []Image) + # GetImage returns information about a single image in storage. # If the image caGetImage returns be found, [ImageNotFound](#ImageNotFound) will be returned. method GetImage(id: string) -> (image: Image) -- cgit v1.2.3-54-g00ecf