Skip to content

Commit f3bc3fe

Browse files
author
zhangyue
committed
feature: support images filter flag
Signed-off-by: zhangyue <[email protected]>
1 parent 9bf53d1 commit f3bc3fe

File tree

16 files changed

+257
-34
lines changed

16 files changed

+257
-34
lines changed

apis/filters/parse.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package filters
33
import (
44
"encoding/json"
55
"errors"
6+
"path"
67
"strings"
78
)
89

@@ -36,6 +37,12 @@ func NewArgs(initialArgs ...KeyValuePair) Args {
3637
return args
3738
}
3839

40+
// Contains returns true if the key exists in the mapping
41+
func (args Args) Contains(field string) bool {
42+
_, ok := args.fields[field]
43+
return ok
44+
}
45+
3946
// Get returns the list of values associated with the key
4047
func (args Args) Get(key string) []string {
4148
values := args.fields[key]
@@ -150,3 +157,33 @@ func FromParam(p string) (Args, error) {
150157
}
151158
return args, nil
152159
}
160+
161+
//FromFilterOpts parse key=value to Args string from cli opts
162+
func FromFilterOpts(filter []string) (Args, error) {
163+
filterArgs := NewArgs()
164+
165+
for _, f := range filter {
166+
var err error
167+
filterArgs, err = ParseFlag(f, filterArgs)
168+
if err != nil {
169+
return filterArgs, err
170+
}
171+
}
172+
return filterArgs, nil
173+
}
174+
175+
// Validate compared the set of accepted keys against the keys in the mapping.
176+
// An error is returned if any mapping keys are not in the accepted set.
177+
func (args Args) Validate(accepted map[string]bool) error {
178+
for name := range args.fields {
179+
if !accepted[name] {
180+
return errors.New("Invalid filter " + name)
181+
}
182+
}
183+
return nil
184+
}
185+
186+
//FamiliarMatch decide the ref match the pattern or not
187+
func FamiliarMatch(pattern string, ref string) (bool, error) {
188+
return path.Match(pattern, ref)
189+
}

apis/filters/parse_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,30 @@ func TestFromParam(t *testing.T) {
149149
}
150150
}
151151
}
152+
153+
func TestFromFilterOpts(t *testing.T) {
154+
filterOpts := []string{
155+
"reference=img1",
156+
"since=img2",
157+
"before=img3",
158+
"reference=img3",
159+
}
160+
161+
args, err := FromFilterOpts(filterOpts)
162+
if err != nil {
163+
t.Fatal(err)
164+
}
165+
166+
images := args.Get("reference")
167+
if len(images) != 2 {
168+
t.Fatal("Expected two values of reference key, but got one.")
169+
}
170+
171+
if !args.Contains("since") {
172+
t.Fatal("Excepted get since key, but got none.")
173+
}
174+
175+
if !args.Contains("before") {
176+
t.Fatal("Excepted get before key, but got none.")
177+
}
178+
}

apis/server/image_bridge.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strings"
1111
"time"
1212

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

7778
func (s *Server) listImages(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
78-
filters := req.FormValue("filters")
79+
filter, err := filters.FromParam(req.FormValue("filters"))
80+
if err != nil {
81+
return err
82+
}
7983

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

9296
searchResultItem, err := s.ImageMgr.SearchImages(ctx, searchPattern, registry)
9397
if err != nil {
94-
logrus.Errorf("failed to search images from resgitry: %v", err)
98+
logrus.Errorf("failed to search images from registry: %v", err)
9599
return err
96100
}
97101
return EncodeResponse(rw, http.StatusOK, searchResultItem)

apis/swagger.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,6 @@ paths:
348348
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
349349
350350
- `before`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
351-
- `dangling=true`
352-
- `label=key` or `label="key=value"` of an image label
353351
- `reference`=(`<image-name>[:<tag>]`)
354352
- `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
355353
type: "string"

cli/events.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,9 @@ func (e *EventsCommand) runEvents() error {
5959
ctx := context.Background()
6060
apiClient := e.cli.Client()
6161

62-
eventFilterArgs := filters.NewArgs()
63-
64-
// TODO: parse params
65-
for _, f := range e.filter {
66-
var err error
67-
eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
68-
if err != nil {
69-
return err
70-
}
62+
eventFilterArgs, err := filters.FromFilterOpts(e.filter)
63+
if err != nil {
64+
return err
7165
}
7266

7367
responseBody, err := apiClient.Events(ctx, e.since, e.until, eventFilterArgs)

cli/image_list.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import (
44
"context"
55
"fmt"
66

7+
"github.com/alibaba/pouch/apis/filters"
78
"github.com/alibaba/pouch/apis/types"
89
"github.com/alibaba/pouch/pkg/reference"
910
"github.com/alibaba/pouch/pkg/utils"
1011

11-
digest "github.com/opencontainers/go-digest"
12+
"github.com/opencontainers/go-digest"
1213
"github.com/spf13/cobra"
1314
)
1415

@@ -38,6 +39,7 @@ type ImagesCommand struct {
3839
flagQuiet bool
3940
flagDigest bool
4041
flagNoTrunc bool
42+
flagFilter []string
4143
}
4244

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

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

73-
imageList, err := apiClient.ImageList(ctx)
76+
imageFilterArgs, err := filters.FromFilterOpts(i.flagFilter)
7477
if err != nil {
75-
return fmt.Errorf("failed to get image list: %v", err)
78+
return err
79+
}
7680

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

7986
if i.flagQuiet {

client/image_list.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,26 @@ package client
22

33
import (
44
"context"
5+
"net/url"
56

7+
"github.com/alibaba/pouch/apis/filters"
68
"github.com/alibaba/pouch/apis/types"
79
)
810

911
// ImageList requests daemon to list all images
10-
func (client *APIClient) ImageList(ctx context.Context) ([]types.ImageInfo, error) {
11-
resp, err := client.get(ctx, "/images/json", nil, nil)
12+
func (client *APIClient) ImageList(ctx context.Context, filter filters.Args) ([]types.ImageInfo, error) {
13+
query := url.Values{}
14+
15+
if filter.Len() > 0 {
16+
filtersJSON, err := filters.ToParam(filter)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
query.Set("filters", filtersJSON)
22+
}
23+
24+
resp, err := client.get(ctx, "/images/json", query, nil)
1225
if err != nil {
1326
return nil, err
1427
}
@@ -19,5 +32,4 @@ func (client *APIClient) ImageList(ctx context.Context) ([]types.ImageInfo, erro
1932
ensureCloseReader(resp)
2033

2134
return imageList, err
22-
2335
}

client/image_list_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ import (
1212

1313
"github.com/alibaba/pouch/apis/types"
1414

15+
"github.com/alibaba/pouch/apis/filters"
1516
"github.com/stretchr/testify/assert"
1617
)
1718

1819
func TestImageListServerError(t *testing.T) {
1920
client := &APIClient{
2021
HTTPCli: newMockClient(errorMockResponse(http.StatusInternalServerError, "Server error")),
2122
}
22-
_, err := client.ImageList(context.Background())
23+
_, err := client.ImageList(context.Background(), filters.NewArgs())
2324
if err == nil || !strings.Contains(err.Error(), "Server error") {
2425
t.Fatalf("expected a Server Error, got %v", err)
2526
}
@@ -62,7 +63,7 @@ func TestImageList(t *testing.T) {
6263
HTTPCli: httpClient,
6364
}
6465

65-
image, err := client.ImageList(context.Background())
66+
image, err := client.ImageList(context.Background(), filters.NewArgs())
6667
if err != nil {
6768
t.Fatal(err)
6869
}

client/interface.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ type ContainerAPIClient interface {
4949

5050
// ImageAPIClient defines methods of Image client.
5151
type ImageAPIClient interface {
52-
ImageList(ctx context.Context) ([]types.ImageInfo, error)
52+
ImageList(ctx context.Context, filters filters.Args) ([]types.ImageInfo, error)
5353
ImageInspect(ctx context.Context, name string) (types.ImageInfo, error)
5454
ImagePull(ctx context.Context, name, tag, encodedAuth string) (io.ReadCloser, error)
5555
ImageRemove(ctx context.Context, name string, force bool) error

cri/v1alpha1/cri.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
goruntime "runtime"
1414
"time"
1515

16+
"github.com/alibaba/pouch/apis/filters"
1617
apitypes "github.com/alibaba/pouch/apis/types"
1718
anno "github.com/alibaba/pouch/cri/annotations"
1819
cni "github.com/alibaba/pouch/cri/ocicni"
@@ -1023,7 +1024,7 @@ func (c *CriManager) Status(ctx context.Context, r *runtime.StatusRequest) (*run
10231024
// ListImages lists existing images.
10241025
func (c *CriManager) ListImages(ctx context.Context, r *runtime.ListImagesRequest) (*runtime.ListImagesResponse, error) {
10251026
// TODO: handle image list filters.
1026-
imageList, err := c.ImageMgr.ListImages(ctx, "")
1027+
imageList, err := c.ImageMgr.ListImages(ctx, filters.NewArgs())
10271028
if err != nil {
10281029
return nil, err
10291030
}

0 commit comments

Comments
 (0)