Add reference filter and deprecated filter param…
| ... | ... |
@@ -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 |
|