1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

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>
This commit is contained in:
Vincent Demeester 2016-11-11 15:34:01 +01:00
parent 90d10203a4
commit 820b809e70
No known key found for this signature in database
GPG key ID: 083CC6FD6EB699A3
10 changed files with 53 additions and 56 deletions

View file

@ -5,6 +5,7 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend" "github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -25,7 +26,7 @@ type containerBackend interface {
type imageBackend interface { type imageBackend interface {
ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error) ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error)
ImageHistory(imageName string) ([]*types.ImageHistory, 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) LookupImage(name string) (*types.ImageInspect, error)
TagImage(imageName, repository, tag string) error TagImage(imageName, repository, tag string) error
ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error) ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error)

View file

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

View file

@ -202,7 +202,6 @@ type ImageImportOptions struct {
// ImageListOptions holds parameters to filter the list of images with. // ImageListOptions holds parameters to filter the list of images with.
type ImageListOptions struct { type ImageListOptions struct {
MatchName string
All bool All bool
Filters filters.Args Filters filters.Args
} }

View file

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

View file

@ -21,10 +21,6 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
} }
query.Set("filters", filterJSON) 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 { if options.All {
query.Set("all", "1") query.Set("all", "1")
} }

View file

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

View file

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

View file

@ -3,18 +3,17 @@ package daemon
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"path"
"sort" "sort"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/container" "github.com/docker/docker/container"
"github.com/docker/docker/image" "github.com/docker/docker/image"
"github.com/docker/docker/layer" "github.com/docker/docker/layer"
"github.com/docker/docker/reference"
) )
var acceptedImageFilterTags = map[string]bool{ var acceptedImageFilterTags = map[string]bool{
@ -22,6 +21,7 @@ var acceptedImageFilterTags = map[string]bool{
"label": true, "label": true,
"before": true, "before": true,
"since": true, "since": true,
"reference": true,
} }
// byCreated is a temporary type used to sort a list of images by creation // 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 // 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 // named all controls whether all images in the graph are filtered, or just
// the heads. // 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 ( var (
allImages map[image.ID]*image.Image allImages map[image.ID]*image.Image
err error err error
danglingOnly = false danglingOnly = false
) )
imageFilters, err := filters.FromParam(filterArgs)
if err != nil {
return nil, err
}
if err := imageFilters.Validate(acceptedImageFilterTags); err != nil { if err := imageFilters.Validate(acceptedImageFilterTags); err != nil {
return nil, err 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 allLayers map[layer.ChainID]layer.Layer
var allContainers []*container.Container 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 { for id, img := range allImages {
if beforeFilter != nil { if beforeFilter != nil {
if img.Created.Equal(beforeFilter.Created) || img.Created.After(beforeFilter.Created) { 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) newImage := newImage(img, size)
for _, ref := range daemon.referenceStore.References(id.Digest()) { for _, ref := range daemon.referenceStore.References(id.Digest()) {
if filter != "" { // filter by tag/repo name if imageFilters.Include("reference") {
if filterTagged { // filter by tag, require full ref match var found bool
if ref.String() != filter { var matchErr error
continue 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 continue
} }
} }
@ -168,7 +158,7 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs
//dangling=false case, so dangling image is not needed //dangling=false case, so dangling image is not needed
continue 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 continue
} }
newImage.RepoDigests = []string{"<none>@<none>"} newImage.RepoDigests = []string{"<none>@<none>"}

View file

@ -20,23 +20,29 @@ The following list of features are deprecated in Engine.
To learn more about Docker Engine's deprecation policy, To learn more about Docker Engine's deprecation policy,
see [Feature Deprecation Policy](https://docs.docker.com/engine/#feature-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 ### `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** **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. `repository:shortid` syntax for referencing images is very little used, collides with with tag references can be confused with digest references.
### `docker daemon` subcommand ### `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** **Target For Removal In Release: v1.16**
The daemon is moved to a separate binary (`dockerd`), and should be used instead. The daemon is moved to a separate binary (`dockerd`), and should be used instead.
### Duplicate keys with conflicting values in engine labels ### 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** **Target For Removal In Release: v1.16**

View file

@ -1733,7 +1733,7 @@ references on the command line.
- `label=key` or `label="key=value"` of an image label - `label=key` or `label="key=value"` of an image label
- `before`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) - `before`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
- `since`=(`<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 ### Build image from a Dockerfile