Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions apis/filters/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package filters
import (
"encoding/json"
"errors"
"path"
"strings"
)

Expand Down Expand Up @@ -36,6 +37,12 @@ func NewArgs(initialArgs ...KeyValuePair) Args {
return args
}

// Contains returns true if the key exists in the mapping
func (args Args) Contains(field string) bool {
_, ok := args.fields[field]
return ok
}

// Get returns the list of values associated with the key
func (args Args) Get(key string) []string {
values := args.fields[key]
Expand Down Expand Up @@ -150,3 +157,33 @@ func FromParam(p string) (Args, error) {
}
return args, nil
}

// FromFilterOpts parse key=value to Args string from cli opts
func FromFilterOpts(filter []string) (Args, error) {
filterArgs := NewArgs()

for _, f := range filter {
var err error
filterArgs, err = ParseFlag(f, filterArgs)
if err != nil {
return filterArgs, err
}
}
return filterArgs, nil
}

// Validate compared the set of accepted keys against the keys in the mapping.
// An error is returned if any mapping keys are not in the accepted set.
func (args Args) Validate(accepted map[string]bool) error {
for name := range args.fields {
if !accepted[name] {
return errors.New("invalid filter " + name)
}
}
return nil
}

// FamiliarMatch decide the ref match the pattern or not
func FamiliarMatch(pattern string, ref string) (bool, error) {
return path.Match(pattern, ref)
}
27 changes: 27 additions & 0 deletions apis/filters/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,30 @@ func TestFromParam(t *testing.T) {
}
}
}

func TestFromFilterOpts(t *testing.T) {
filterOpts := []string{
"reference=img1",
"since=img2",
"before=img3",
"reference=img3",
}

args, err := FromFilterOpts(filterOpts)
if err != nil {
t.Fatal(err)
}

images := args.Get("reference")
if len(images) != 2 {
t.Fatal("Expected two values of reference key, but got one.")
}

if !args.Contains("since") {
t.Fatal("Excepted get since key, but got none.")
}

if !args.Contains("before") {
t.Fatal("Excepted get before key, but got none.")
}
}
10 changes: 7 additions & 3 deletions apis/server/image_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

"github.com/alibaba/pouch/apis/filters"
"github.com/alibaba/pouch/apis/metrics"
"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/daemon/mgr"
Expand Down Expand Up @@ -75,9 +76,12 @@ func (s *Server) getImage(ctx context.Context, rw http.ResponseWriter, req *http
}

func (s *Server) listImages(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
filters := req.FormValue("filters")
filter, err := filters.FromParam(req.FormValue("filters"))
if err != nil {
return err
}

imageList, err := s.ImageMgr.ListImages(ctx, filters)
imageList, err := s.ImageMgr.ListImages(ctx, filter)
if err != nil {
logrus.Errorf("failed to list images: %v", err)
return err
Expand All @@ -91,7 +95,7 @@ func (s *Server) searchImages(ctx context.Context, rw http.ResponseWriter, req *

searchResultItem, err := s.ImageMgr.SearchImages(ctx, searchPattern, registry)
if err != nil {
logrus.Errorf("failed to search images from resgitry: %v", err)
logrus.Errorf("failed to search images from registry: %v", err)
return err
}
return EncodeResponse(rw, http.StatusOK, searchResultItem)
Expand Down
2 changes: 0 additions & 2 deletions apis/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,6 @@ paths:
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:

- `before`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
- `dangling=true`
- `label=key` or `label="key=value"` of an image label
- `reference`=(`<image-name>[:<tag>]`)
- `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
type: "string"
Expand Down
12 changes: 3 additions & 9 deletions cli/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,9 @@ func (e *EventsCommand) runEvents() error {
ctx := context.Background()
apiClient := e.cli.Client()

eventFilterArgs := filters.NewArgs()

// TODO: parse params
for _, f := range e.filter {
var err error
eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
if err != nil {
return err
}
eventFilterArgs, err := filters.FromFilterOpts(e.filter)
if err != nil {
return err
}

responseBody, err := apiClient.Events(ctx, e.since, e.until, eventFilterArgs)
Expand Down
13 changes: 10 additions & 3 deletions cli/image_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"context"
"fmt"

"github.com/alibaba/pouch/apis/filters"
"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/pkg/reference"
"github.com/alibaba/pouch/pkg/utils"

digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/go-digest"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -38,6 +39,7 @@ type ImagesCommand struct {
flagQuiet bool
flagDigest bool
flagNoTrunc bool
flagFilter []string
}

// Init initialize images command.
Expand All @@ -63,17 +65,22 @@ func (i *ImagesCommand) addFlags() {
flagSet.BoolVarP(&i.flagQuiet, "quiet", "q", false, "Only show image numeric ID")
flagSet.BoolVar(&i.flagDigest, "digest", false, "Show images with digest")
flagSet.BoolVar(&i.flagNoTrunc, "no-trunc", false, "Do not truncate output")
flagSet.StringSliceVarP(&i.flagFilter, "filter", "f", []string{}, "Filter output based on conditions provided, filter support reference, since, before")
}

// runImages is the entry of images container command.
func (i *ImagesCommand) runImages(args []string) error {
ctx := context.Background()
apiClient := i.cli.Client()

imageList, err := apiClient.ImageList(ctx)
imageFilterArgs, err := filters.FromFilterOpts(i.flagFilter)
if err != nil {
return fmt.Errorf("failed to get image list: %v", err)
return err
}

imageList, err := apiClient.ImageList(ctx, imageFilterArgs)
if err != nil {
return fmt.Errorf("failed to get image list: %v", err)
}

if i.flagQuiet {
Expand Down
18 changes: 15 additions & 3 deletions client/image_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@ package client

import (
"context"
"net/url"

"github.com/alibaba/pouch/apis/filters"
"github.com/alibaba/pouch/apis/types"
)

// ImageList requests daemon to list all images
func (client *APIClient) ImageList(ctx context.Context) ([]types.ImageInfo, error) {
resp, err := client.get(ctx, "/images/json", nil, nil)
func (client *APIClient) ImageList(ctx context.Context, filter filters.Args) ([]types.ImageInfo, error) {
query := url.Values{}

if filter.Len() > 0 {
filtersJSON, err := filters.ToParam(filter)
if err != nil {
return nil, err
}

query.Set("filters", filtersJSON)
}

resp, err := client.get(ctx, "/images/json", query, nil)
if err != nil {
return nil, err
}
Expand All @@ -19,5 +32,4 @@ func (client *APIClient) ImageList(ctx context.Context) ([]types.ImageInfo, erro
ensureCloseReader(resp)

return imageList, err

}
5 changes: 3 additions & 2 deletions client/image_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"testing"

"github.com/alibaba/pouch/apis/filters"
"github.com/alibaba/pouch/apis/types"

"github.com/stretchr/testify/assert"
Expand All @@ -19,7 +20,7 @@ func TestImageListServerError(t *testing.T) {
client := &APIClient{
HTTPCli: newMockClient(errorMockResponse(http.StatusInternalServerError, "Server error")),
}
_, err := client.ImageList(context.Background())
_, err := client.ImageList(context.Background(), filters.NewArgs())
if err == nil || !strings.Contains(err.Error(), "Server error") {
t.Fatalf("expected a Server Error, got %v", err)
}
Expand Down Expand Up @@ -62,7 +63,7 @@ func TestImageList(t *testing.T) {
HTTPCli: httpClient,
}

image, err := client.ImageList(context.Background())
image, err := client.ImageList(context.Background(), filters.NewArgs())
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type ContainerAPIClient interface {

// ImageAPIClient defines methods of Image client.
type ImageAPIClient interface {
ImageList(ctx context.Context) ([]types.ImageInfo, error)
ImageList(ctx context.Context, filters filters.Args) ([]types.ImageInfo, error)
ImageInspect(ctx context.Context, name string) (types.ImageInfo, error)
ImagePull(ctx context.Context, name, tag, encodedAuth string) (io.ReadCloser, error)
ImageRemove(ctx context.Context, name string, force bool) error
Expand Down
3 changes: 2 additions & 1 deletion cri/v1alpha1/cri.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
goruntime "runtime"
"time"

"github.com/alibaba/pouch/apis/filters"
apitypes "github.com/alibaba/pouch/apis/types"
anno "github.com/alibaba/pouch/cri/annotations"
cni "github.com/alibaba/pouch/cri/ocicni"
Expand Down Expand Up @@ -1023,7 +1024,7 @@ func (c *CriManager) Status(ctx context.Context, r *runtime.StatusRequest) (*run
// ListImages lists existing images.
func (c *CriManager) ListImages(ctx context.Context, r *runtime.ListImagesRequest) (*runtime.ListImagesResponse, error) {
// TODO: handle image list filters.
imageList, err := c.ImageMgr.ListImages(ctx, "")
imageList, err := c.ImageMgr.ListImages(ctx, filters.NewArgs())
if err != nil {
return nil, err
}
Expand Down
3 changes: 2 additions & 1 deletion cri/v1alpha2/cri.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"strconv"
"time"

"github.com/alibaba/pouch/apis/filters"
apitypes "github.com/alibaba/pouch/apis/types"
anno "github.com/alibaba/pouch/cri/annotations"
runtime "github.com/alibaba/pouch/cri/apis/v1alpha2"
Expand Down Expand Up @@ -1307,7 +1308,7 @@ func (c *CriManager) ListImages(ctx context.Context, r *runtime.ListImagesReques
}(time.Now())

// TODO: handle image list filters.
imageList, err := c.ImageMgr.ListImages(ctx, "")
imageList, err := c.ImageMgr.ListImages(ctx, filters.NewArgs())
if err != nil {
return nil, err
}
Expand Down
Loading