Browse code

Merge pull request #27872 from vdemeester/images-filter-filters

Add reference filter and deprecated filter param…

Brian Goff authored on 2016/11/12 01:24:19
Showing 10 changed files
... ...
@@ -5,6 +5,7 @@ import (
5 5
 
6 6
 	"github.com/docker/docker/api/types"
7 7
 	"github.com/docker/docker/api/types/backend"
8
+	"github.com/docker/docker/api/types/filters"
8 9
 	"github.com/docker/docker/api/types/registry"
9 10
 	"golang.org/x/net/context"
10 11
 )
... ...
@@ -25,7 +26,7 @@ type containerBackend interface {
25 25
 type imageBackend interface {
26 26
 	ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error)
27 27
 	ImageHistory(imageName string) ([]*types.ImageHistory, error)
28
-	Images(filterArgs string, filter string, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error)
28
+	Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error)
29 29
 	LookupImage(name string) (*types.ImageInspect, error)
30 30
 	TagImage(imageName, repository, tag string) error
31 31
 	ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error)
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/docker/api/types"
14 14
 	"github.com/docker/docker/api/types/backend"
15 15
 	"github.com/docker/docker/api/types/container"
16
+	"github.com/docker/docker/api/types/filters"
16 17
 	"github.com/docker/docker/api/types/versions"
17 18
 	"github.com/docker/docker/pkg/ioutils"
18 19
 	"github.com/docker/docker/pkg/streamformatter"
... ...
@@ -247,8 +248,18 @@ func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
247 247
 		return err
248 248
 	}
249 249
 
250
-	// FIXME: The filter parameter could just be a match filter
251
-	images, err := s.backend.Images(r.Form.Get("filters"), r.Form.Get("filter"), httputils.BoolValue(r, "all"), false)
250
+	imageFilters, err := filters.FromParam(r.Form.Get("filters"))
251
+	if err != nil {
252
+		return err
253
+	}
254
+
255
+	version := httputils.VersionFromContext(ctx)
256
+	filterParam := r.Form.Get("filter")
257
+	if versions.LessThan(version, "1.28") && filterParam != "" {
258
+		imageFilters.Add("reference", filterParam)
259
+	}
260
+
261
+	images, err := s.backend.Images(imageFilters, httputils.BoolValue(r, "all"), false)
252 262
 	if err != nil {
253 263
 		return err
254 264
 	}
... ...
@@ -202,9 +202,8 @@ type ImageImportOptions struct {
202 202
 
203 203
 // ImageListOptions holds parameters to filter the list of images with.
204 204
 type ImageListOptions struct {
205
-	MatchName string
206
-	All       bool
207
-	Filters   filters.Args
205
+	All     bool
206
+	Filters filters.Args
208 207
 }
209 208
 
210 209
 // ImageLoadResponse returns information to the client about a load process.
... ...
@@ -60,10 +60,14 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
60 60
 func runImages(dockerCli *command.DockerCli, opts imagesOptions) error {
61 61
 	ctx := context.Background()
62 62
 
63
+	filters := opts.filter.Value()
64
+	if opts.matchName != "" {
65
+		filters.Add("reference", opts.matchName)
66
+	}
67
+
63 68
 	options := types.ImageListOptions{
64
-		MatchName: opts.matchName,
65
-		All:       opts.all,
66
-		Filters:   opts.filter.Value(),
69
+		All:     opts.all,
70
+		Filters: filters,
67 71
 	}
68 72
 
69 73
 	images, err := dockerCli.Client().ImageList(ctx, options)
... ...
@@ -21,10 +21,6 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
21 21
 		}
22 22
 		query.Set("filters", filterJSON)
23 23
 	}
24
-	if options.MatchName != "" {
25
-		// FIXME rename this parameter, to not be confused with the filters flag
26
-		query.Set("filter", options.MatchName)
27
-	}
28 24
 	if options.All {
29 25
 		query.Set("all", "1")
30 26
 	}
... ...
@@ -50,17 +50,6 @@ func TestImageList(t *testing.T) {
50 50
 		},
51 51
 		{
52 52
 			options: types.ImageListOptions{
53
-				All:       true,
54
-				MatchName: "image_name",
55
-			},
56
-			expectedQueryParams: map[string]string{
57
-				"all":     "1",
58
-				"filter":  "image_name",
59
-				"filters": "",
60
-			},
61
-		},
62
-		{
63
-			options: types.ImageListOptions{
64 53
 				Filters: filters,
65 54
 			},
66 55
 			expectedQueryParams: map[string]string{
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"github.com/Sirupsen/logrus"
7 7
 	"github.com/docker/distribution/digest"
8 8
 	"github.com/docker/docker/api/types"
9
+	"github.com/docker/docker/api/types/filters"
9 10
 	"github.com/docker/docker/layer"
10 11
 	"github.com/docker/docker/pkg/directory"
11 12
 	"github.com/docker/docker/volume"
... ...
@@ -44,7 +45,7 @@ func (daemon *Daemon) SystemDiskUsage() (*types.DiskUsage, error) {
44 44
 	}
45 45
 
46 46
 	// Get all top images with extra attributes
47
-	allImages, err := daemon.Images("", "", false, true)
47
+	allImages, err := daemon.Images(filters.NewArgs(), false, true)
48 48
 	if err != nil {
49 49
 		return nil, fmt.Errorf("failed to retrieve image list: %v", err)
50 50
 	}
... ...
@@ -3,25 +3,25 @@ package daemon
3 3
 import (
4 4
 	"encoding/json"
5 5
 	"fmt"
6
-	"path"
7 6
 	"sort"
8 7
 	"time"
9 8
 
10 9
 	"github.com/pkg/errors"
11 10
 
11
+	"github.com/docker/distribution/reference"
12 12
 	"github.com/docker/docker/api/types"
13 13
 	"github.com/docker/docker/api/types/filters"
14 14
 	"github.com/docker/docker/container"
15 15
 	"github.com/docker/docker/image"
16 16
 	"github.com/docker/docker/layer"
17
-	"github.com/docker/docker/reference"
18 17
 )
19 18
 
20 19
 var acceptedImageFilterTags = map[string]bool{
21
-	"dangling": true,
22
-	"label":    true,
23
-	"before":   true,
24
-	"since":    true,
20
+	"dangling":  true,
21
+	"label":     true,
22
+	"before":    true,
23
+	"since":     true,
24
+	"reference": true,
25 25
 }
26 26
 
27 27
 // byCreated is a temporary type used to sort a list of images by creation
... ...
@@ -42,17 +42,13 @@ func (daemon *Daemon) Map() map[image.ID]*image.Image {
42 42
 // filter is a shell glob string applied to repository names. The argument
43 43
 // named all controls whether all images in the graph are filtered, or just
44 44
 // the heads.
45
-func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) {
45
+func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) {
46 46
 	var (
47 47
 		allImages    map[image.ID]*image.Image
48 48
 		err          error
49 49
 		danglingOnly = false
50 50
 	)
51 51
 
52
-	imageFilters, err := filters.FromParam(filterArgs)
53
-	if err != nil {
54
-		return nil, err
55
-	}
56 52
 	if err := imageFilters.Validate(acceptedImageFilterTags); err != nil {
57 53
 		return nil, err
58 54
 	}
... ...
@@ -93,16 +89,6 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs
93 93
 	var allLayers map[layer.ChainID]layer.Layer
94 94
 	var allContainers []*container.Container
95 95
 
96
-	var filterTagged bool
97
-	if filter != "" {
98
-		filterRef, err := reference.ParseNamed(filter)
99
-		if err == nil { // parse error means wildcard repo
100
-			if _, ok := filterRef.(reference.NamedTagged); ok {
101
-				filterTagged = true
102
-			}
103
-		}
104
-	}
105
-
106 96
 	for id, img := range allImages {
107 97
 		if beforeFilter != nil {
108 98
 			if img.Created.Equal(beforeFilter.Created) || img.Created.After(beforeFilter.Created) {
... ...
@@ -145,12 +131,16 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs
145 145
 		newImage := newImage(img, size)
146 146
 
147 147
 		for _, ref := range daemon.referenceStore.References(id.Digest()) {
148
-			if filter != "" { // filter by tag/repo name
149
-				if filterTagged { // filter by tag, require full ref match
150
-					if ref.String() != filter {
151
-						continue
148
+			if imageFilters.Include("reference") {
149
+				var found bool
150
+				var matchErr error
151
+				for _, pattern := range imageFilters.Get("reference") {
152
+					found, matchErr = reference.Match(pattern, ref)
153
+					if matchErr != nil {
154
+						return nil, matchErr
152 155
 					}
153
-				} else if matched, err := path.Match(filter, ref.Name()); !matched || err != nil { // name only match, FIXME: docs say exact
156
+				}
157
+				if !found {
154 158
 					continue
155 159
 				}
156 160
 			}
... ...
@@ -168,7 +158,7 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs
168 168
 					//dangling=false case, so dangling image is not needed
169 169
 					continue
170 170
 				}
171
-				if filter != "" { // skip images with no references if filtering by tag
171
+				if imageFilters.Include("reference") { // skip images with no references if filtering by reference
172 172
 					continue
173 173
 				}
174 174
 				newImage.RepoDigests = []string{"<none>@<none>"}
... ...
@@ -20,23 +20,29 @@ The following list of features are deprecated in Engine.
20 20
 To learn more about Docker Engine's deprecation policy,
21 21
 see [Feature Deprecation Policy](https://docs.docker.com/engine/#feature-deprecation-policy).
22 22
 
23
+## `filter` param for `/images/json` endpoint
24
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
25
+
26
+**Target For Removal In Release: v1.16**
27
+
28
+The `filter` param to filter the list of image by reference (name or name:tag) is now implemented as a regular filter, named `reference`.
23 29
 
24 30
 ### `repository:shortid` image references
25
-**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/)**
31
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
26 32
 
27 33
 **Target For Removal In Release: v1.16**
28 34
 
29 35
 `repository:shortid` syntax for referencing images is very little used, collides with with tag references can be confused with digest references.
30 36
 
31 37
 ### `docker daemon` subcommand
32
-**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/)**
38
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
33 39
 
34 40
 **Target For Removal In Release: v1.16**
35 41
 
36 42
 The daemon is moved to a separate binary (`dockerd`), and should be used instead.
37 43
 
38 44
 ### Duplicate keys with conflicting values in engine labels
39
-**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/)**
45
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
40 46
 
41 47
 **Target For Removal In Release: v1.16**
42 48
 
... ...
@@ -1733,7 +1733,7 @@ references on the command line.
1733 1733
   -   `label=key` or `label="key=value"` of an image label
1734 1734
   -   `before`=(`<image-name>[:<tag>]`,  `<image id>` or `<image@digest>`)
1735 1735
   -   `since`=(`<image-name>[:<tag>]`,  `<image id>` or `<image@digest>`)
1736
--   **filter** - only return images with the specified name
1736
+  -   `reference`=(`<image-name>[:<tag>]`)
1737 1737
 
1738 1738
 ### Build image from a Dockerfile
1739 1739