Jelajahi Sumber

Add reference filter and deprecated filter param…

… for `docker images`.

This deprecates the `filter` param for the `/images` endpoint and make a
new filter called `reference` to replace it. It does change the CLI
side (still possible to do `docker images busybox:musl`) but changes the
cli code to use the filter instead (so that `docker images --filter
busybox:musl` and `docker images busybox:musl` act the same).

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Vincent Demeester 8 tahun lalu
induk
melakukan
820b809e70

+ 2 - 1
api/server/router/image/backend.go

@@ -5,6 +5,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/backend"
+	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/registry"
 	"golang.org/x/net/context"
 )
@@ -25,7 +26,7 @@ type containerBackend interface {
 type imageBackend interface {
 	ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error)
 	ImageHistory(imageName string) ([]*types.ImageHistory, error)
-	Images(filterArgs string, filter string, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error)
+	Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error)
 	LookupImage(name string) (*types.ImageInspect, error)
 	TagImage(imageName, repository, tag string) error
 	ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error)

+ 13 - 2
api/server/router/image/image_routes.go

@@ -13,6 +13,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/backend"
 	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/streamformatter"
@@ -247,8 +248,18 @@ func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
 		return err
 	}
 
-	// FIXME: The filter parameter could just be a match filter
-	images, err := s.backend.Images(r.Form.Get("filters"), r.Form.Get("filter"), httputils.BoolValue(r, "all"), false)
+	imageFilters, err := filters.FromParam(r.Form.Get("filters"))
+	if err != nil {
+		return err
+	}
+
+	version := httputils.VersionFromContext(ctx)
+	filterParam := r.Form.Get("filter")
+	if versions.LessThan(version, "1.28") && filterParam != "" {
+		imageFilters.Add("reference", filterParam)
+	}
+
+	images, err := s.backend.Images(imageFilters, httputils.BoolValue(r, "all"), false)
 	if err != nil {
 		return err
 	}

+ 2 - 3
api/types/client.go

@@ -202,9 +202,8 @@ type ImageImportOptions struct {
 
 // ImageListOptions holds parameters to filter the list of images with.
 type ImageListOptions struct {
-	MatchName string
-	All       bool
-	Filters   filters.Args
+	All     bool
+	Filters filters.Args
 }
 
 // ImageLoadResponse returns information to the client about a load process.

+ 7 - 3
cli/command/image/list.go

@@ -60,10 +60,14 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
 func runImages(dockerCli *command.DockerCli, opts imagesOptions) error {
 	ctx := context.Background()
 
+	filters := opts.filter.Value()
+	if opts.matchName != "" {
+		filters.Add("reference", opts.matchName)
+	}
+
 	options := types.ImageListOptions{
-		MatchName: opts.matchName,
-		All:       opts.all,
-		Filters:   opts.filter.Value(),
+		All:     opts.all,
+		Filters: filters,
 	}
 
 	images, err := dockerCli.Client().ImageList(ctx, options)

+ 0 - 4
client/image_list.go

@@ -21,10 +21,6 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
 		}
 		query.Set("filters", filterJSON)
 	}
-	if options.MatchName != "" {
-		// FIXME rename this parameter, to not be confused with the filters flag
-		query.Set("filter", options.MatchName)
-	}
 	if options.All {
 		query.Set("all", "1")
 	}

+ 0 - 11
client/image_list_test.go

@@ -48,17 +48,6 @@ func TestImageList(t *testing.T) {
 				"filters": "",
 			},
 		},
-		{
-			options: types.ImageListOptions{
-				All:       true,
-				MatchName: "image_name",
-			},
-			expectedQueryParams: map[string]string{
-				"all":     "1",
-				"filter":  "image_name",
-				"filters": "",
-			},
-		},
 		{
 			options: types.ImageListOptions{
 				Filters: filters,

+ 2 - 1
daemon/disk_usage.go

@@ -6,6 +6,7 @@ import (
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution/digest"
 	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/directory"
 	"github.com/docker/docker/volume"
@@ -44,7 +45,7 @@ func (daemon *Daemon) SystemDiskUsage() (*types.DiskUsage, error) {
 	}
 
 	// Get all top images with extra attributes
-	allImages, err := daemon.Images("", "", false, true)
+	allImages, err := daemon.Images(filters.NewArgs(), false, true)
 	if err != nil {
 		return nil, fmt.Errorf("failed to retrieve image list: %v", err)
 	}

+ 17 - 27
daemon/images.go

@@ -3,25 +3,25 @@ package daemon
 import (
 	"encoding/json"
 	"fmt"
-	"path"
 	"sort"
 	"time"
 
 	"github.com/pkg/errors"
 
+	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
-	"github.com/docker/docker/reference"
 )
 
 var acceptedImageFilterTags = map[string]bool{
-	"dangling": true,
-	"label":    true,
-	"before":   true,
-	"since":    true,
+	"dangling":  true,
+	"label":     true,
+	"before":    true,
+	"since":     true,
+	"reference": true,
 }
 
 // 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 {
 // filter is a shell glob string applied to repository names. The argument
 // named all controls whether all images in the graph are filtered, or just
 // the heads.
-func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) {
+func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) {
 	var (
 		allImages    map[image.ID]*image.Image
 		err          error
 		danglingOnly = false
 	)
 
-	imageFilters, err := filters.FromParam(filterArgs)
-	if err != nil {
-		return nil, err
-	}
 	if err := imageFilters.Validate(acceptedImageFilterTags); err != nil {
 		return nil, err
 	}
@@ -93,16 +89,6 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs
 	var allLayers map[layer.ChainID]layer.Layer
 	var allContainers []*container.Container
 
-	var filterTagged bool
-	if filter != "" {
-		filterRef, err := reference.ParseNamed(filter)
-		if err == nil { // parse error means wildcard repo
-			if _, ok := filterRef.(reference.NamedTagged); ok {
-				filterTagged = true
-			}
-		}
-	}
-
 	for id, img := range allImages {
 		if beforeFilter != nil {
 			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
 		newImage := newImage(img, size)
 
 		for _, ref := range daemon.referenceStore.References(id.Digest()) {
-			if filter != "" { // filter by tag/repo name
-				if filterTagged { // filter by tag, require full ref match
-					if ref.String() != filter {
-						continue
+			if imageFilters.Include("reference") {
+				var found bool
+				var matchErr error
+				for _, pattern := range imageFilters.Get("reference") {
+					found, matchErr = reference.Match(pattern, ref)
+					if matchErr != nil {
+						return nil, matchErr
 					}
-				} else if matched, err := path.Match(filter, ref.Name()); !matched || err != nil { // name only match, FIXME: docs say exact
+				}
+				if !found {
 					continue
 				}
 			}
@@ -168,7 +158,7 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs
 					//dangling=false case, so dangling image is not needed
 					continue
 				}
-				if filter != "" { // skip images with no references if filtering by tag
+				if imageFilters.Include("reference") { // skip images with no references if filtering by reference
 					continue
 				}
 				newImage.RepoDigests = []string{"<none>@<none>"}

+ 9 - 3
docs/deprecated.md

@@ -20,23 +20,29 @@ The following list of features are deprecated in Engine.
 To learn more about Docker Engine's deprecation policy,
 see [Feature Deprecation Policy](https://docs.docker.com/engine/#feature-deprecation-policy).
 
+## `filter` param for `/images/json` endpoint
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
+
+**Target For Removal In Release: v1.16**
+
+The `filter` param to filter the list of image by reference (name or name:tag) is now implemented as a regular filter, named `reference`.
 
 ### `repository:shortid` image references
-**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/)**
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
 
 **Target For Removal In Release: v1.16**
 
 `repository:shortid` syntax for referencing images is very little used, collides with with tag references can be confused with digest references.
 
 ### `docker daemon` subcommand
-**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/)**
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
 
 **Target For Removal In Release: v1.16**
 
 The daemon is moved to a separate binary (`dockerd`), and should be used instead.
 
 ### Duplicate keys with conflicting values in engine labels
-**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/)**
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)**
 
 **Target For Removal In Release: v1.16**
 

+ 1 - 1
docs/reference/api/docker_remote_api_v1.25.md

@@ -1733,7 +1733,7 @@ references on the command line.
   -   `label=key` or `label="key=value"` of an image label
   -   `before`=(`<image-name>[:<tag>]`,  `<image id>` or `<image@digest>`)
   -   `since`=(`<image-name>[:<tag>]`,  `<image id>` or `<image@digest>`)
--   **filter** - only return images with the specified name
+  -   `reference`=(`<image-name>[:<tag>]`)
 
 ### Build image from a Dockerfile