зеркало из https://github.com/microsoft/docker.git
Add before and since filter to images
Add support for two now filter on the `images` command : `before` and `since`. They work the same as the one on the `ps` command but for images. $ docker images --filter before=myimage # display all images older than myimage $ docker images --filter since=myimage # display all images younger than myimage Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Родитель
2a4b4a8133
Коммит
750e16f57c
|
@ -1104,6 +1104,11 @@ _docker_history() {
|
||||||
_docker_images() {
|
_docker_images() {
|
||||||
local key=$(__docker_map_key_of_current_option '--filter|-f')
|
local key=$(__docker_map_key_of_current_option '--filter|-f')
|
||||||
case "$key" in
|
case "$key" in
|
||||||
|
before)
|
||||||
|
cur="${cur##*=}"
|
||||||
|
__docker_complete_images
|
||||||
|
return
|
||||||
|
;;
|
||||||
dangling)
|
dangling)
|
||||||
COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
|
COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
|
||||||
return
|
return
|
||||||
|
@ -1111,11 +1116,16 @@ _docker_images() {
|
||||||
label)
|
label)
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
since)
|
||||||
|
cur="${cur##*=}"
|
||||||
|
__docker_complete_images
|
||||||
|
return
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "$prev" in
|
case "$prev" in
|
||||||
--filter|-f)
|
--filter|-f)
|
||||||
COMPREPLY=( $( compgen -S = -W "dangling label" -- "$cur" ) )
|
COMPREPLY=( $( compgen -S = -W "before dangling label since" -- "$cur" ) )
|
||||||
__docker_nospace
|
__docker_nospace
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -341,10 +341,13 @@ __docker_complete_images_filters() {
|
||||||
declare -a boolean_opts opts
|
declare -a boolean_opts opts
|
||||||
|
|
||||||
boolean_opts=('true' 'false')
|
boolean_opts=('true' 'false')
|
||||||
opts=('dangling' 'label')
|
opts=('before' 'dangling' 'label' 'since')
|
||||||
|
|
||||||
if compset -P '*='; then
|
if compset -P '*='; then
|
||||||
case "${${words[-1]%=*}#*=}" in
|
case "${${words[-1]%=*}#*=}" in
|
||||||
|
(before|since)
|
||||||
|
__docker_images && ret=0
|
||||||
|
;;
|
||||||
(dangling)
|
(dangling)
|
||||||
_describe -t boolean-filter-opts "filter options" boolean_opts && ret=0
|
_describe -t boolean-filter-opts "filter options" boolean_opts && ret=0
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -15,6 +15,8 @@ import (
|
||||||
var acceptedImageFilterTags = map[string]bool{
|
var acceptedImageFilterTags = map[string]bool{
|
||||||
"dangling": true,
|
"dangling": true,
|
||||||
"label": true,
|
"label": true,
|
||||||
|
"before": true,
|
||||||
|
"since": 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
|
||||||
|
@ -63,6 +65,23 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Imag
|
||||||
allImages = daemon.imageStore.Map()
|
allImages = daemon.imageStore.Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var beforeFilter, sinceFilter *image.Image
|
||||||
|
err = imageFilters.WalkValues("before", func(value string) error {
|
||||||
|
beforeFilter, err = daemon.GetImage(value)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imageFilters.WalkValues("since", func(value string) error {
|
||||||
|
sinceFilter, err = daemon.GetImage(value)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
images := []*types.Image{}
|
images := []*types.Image{}
|
||||||
|
|
||||||
var filterTagged bool
|
var filterTagged bool
|
||||||
|
@ -76,6 +95,18 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Imag
|
||||||
}
|
}
|
||||||
|
|
||||||
for id, img := range allImages {
|
for id, img := range allImages {
|
||||||
|
if beforeFilter != nil {
|
||||||
|
if img.Created.Equal(beforeFilter.Created) || img.Created.After(beforeFilter.Created) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sinceFilter != nil {
|
||||||
|
if img.Created.Equal(sinceFilter.Created) || img.Created.Before(sinceFilter.Created) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if imageFilters.Include("label") {
|
if imageFilters.Include("label") {
|
||||||
// Very old image that do not have image.Config (or even labels)
|
// Very old image that do not have image.Config (or even labels)
|
||||||
if img.Config == nil {
|
if img.Config == nil {
|
||||||
|
|
|
@ -75,12 +75,6 @@ type listContext struct {
|
||||||
// exitAllowed is a list of exit codes allowed to filter with
|
// exitAllowed is a list of exit codes allowed to filter with
|
||||||
exitAllowed []int
|
exitAllowed []int
|
||||||
|
|
||||||
// FIXME Remove this for 1.12 as --since and --before are deprecated
|
|
||||||
// beforeContainer is a filter to ignore containers that appear before the one given
|
|
||||||
beforeContainer *container.Container
|
|
||||||
// sinceContainer is a filter to stop the filtering when the iterator arrive to the given container
|
|
||||||
sinceContainer *container.Container
|
|
||||||
|
|
||||||
// beforeFilter is a filter to ignore containers that appear before the one given
|
// beforeFilter is a filter to ignore containers that appear before the one given
|
||||||
// this is used for --filter=before= and --before=, the latter is deprecated.
|
// this is used for --filter=before= and --before=, the latter is deprecated.
|
||||||
beforeFilter *container.Container
|
beforeFilter *container.Container
|
||||||
|
|
|
@ -121,6 +121,7 @@ This section lists each version from latest to oldest. Each listing includes a
|
||||||
* `GET /images/search` now takes a `filters` query parameter.
|
* `GET /images/search` now takes a `filters` query parameter.
|
||||||
* `GET /events` now supports a `reload` event that is emitted when the daemon configuration is reloaded.
|
* `GET /events` now supports a `reload` event that is emitted when the daemon configuration is reloaded.
|
||||||
* `GET /events` now supports filtering by daemon name or ID.
|
* `GET /events` now supports filtering by daemon name or ID.
|
||||||
|
* `GET /images/json` now supports filters `since` and `before`.
|
||||||
|
|
||||||
### v1.23 API changes
|
### v1.23 API changes
|
||||||
|
|
||||||
|
|
|
@ -1628,6 +1628,8 @@ Query Parameters:
|
||||||
- **filters** – a JSON encoded value of the filters (a map[string][]string) to process on the images list. Available filters:
|
- **filters** – a JSON encoded value of the filters (a map[string][]string) to process on the images list. Available filters:
|
||||||
- `dangling=true`
|
- `dangling=true`
|
||||||
- `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>`)
|
||||||
|
- `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
|
||||||
- **filter** - only return images with the specified name
|
- **filter** - only return images with the specified name
|
||||||
|
|
||||||
### Build image from a Dockerfile
|
### Build image from a Dockerfile
|
||||||
|
|
|
@ -16,7 +16,11 @@ parent = "smn_cli"
|
||||||
|
|
||||||
-a, --all Show all images (default hides intermediate images)
|
-a, --all Show all images (default hides intermediate images)
|
||||||
--digests Show digests
|
--digests Show digests
|
||||||
-f, --filter=[] Filter output based on conditions provided
|
-f, --filter=[] Filter output based on these conditions:
|
||||||
|
- dangling=(true|false)
|
||||||
|
- label=<key> or label=<key>=<value>
|
||||||
|
- before=(<image-name>[:tag]|<image-id>|<image@digest>)
|
||||||
|
- since=(<image-name>[:tag]|<image-id>|<image@digest>)
|
||||||
--help Print usage
|
--help Print usage
|
||||||
--no-trunc Don't truncate output
|
--no-trunc Don't truncate output
|
||||||
-q, --quiet Only show numeric IDs
|
-q, --quiet Only show numeric IDs
|
||||||
|
@ -121,6 +125,8 @@ The currently supported filters are:
|
||||||
|
|
||||||
* dangling (boolean - true or false)
|
* dangling (boolean - true or false)
|
||||||
* label (`label=<key>` or `label=<key>=<value>`)
|
* label (`label=<key>` or `label=<key>=<value>`)
|
||||||
|
* before (`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) - filters images created before given id or references
|
||||||
|
* since (`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) - filters images created since given id or references
|
||||||
|
|
||||||
##### Untagged images (dangling)
|
##### Untagged images (dangling)
|
||||||
|
|
||||||
|
@ -165,19 +171,56 @@ The following filter matches images with the `com.example.version` label regardl
|
||||||
|
|
||||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
match-me-1 latest eeae25ada2aa About a minute ago 188.3 MB
|
match-me-1 latest eeae25ada2aa About a minute ago 188.3 MB
|
||||||
match-me-2 latest eeae25ada2aa About a minute ago 188.3 MB
|
match-me-2 latest dea752e4e117 About a minute ago 188.3 MB
|
||||||
|
|
||||||
The following filter matches images with the `com.example.version` label with the `1.0` value.
|
The following filter matches images with the `com.example.version` label with the `1.0` value.
|
||||||
|
|
||||||
$ docker images --filter "label=com.example.version=1.0"
|
$ docker images --filter "label=com.example.version=1.0"
|
||||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
match-me latest eeae25ada2aa About a minute ago 188.3 MB
|
match-me latest 511136ea3c5a About a minute ago 188.3 MB
|
||||||
|
|
||||||
In this example, with the `0.1` value, it returns an empty set because no matches were found.
|
In this example, with the `0.1` value, it returns an empty set because no matches were found.
|
||||||
|
|
||||||
$ docker images --filter "label=com.example.version=0.1"
|
$ docker images --filter "label=com.example.version=0.1"
|
||||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
|
||||||
|
#### Before
|
||||||
|
|
||||||
|
The `before` filter shows only images created before the image with
|
||||||
|
given id or reference. For example, having these images:
|
||||||
|
|
||||||
|
$ docker images
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
image1 latest eeae25ada2aa 4 minutes ago 188.3 MB
|
||||||
|
image2 latest dea752e4e117 9 minutes ago 188.3 MB
|
||||||
|
image3 latest 511136ea3c5a 25 minutes ago 188.3 MB
|
||||||
|
|
||||||
|
Filtering with `before` would give:
|
||||||
|
|
||||||
|
$ docker images --filter "before=image1"
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
image2 latest dea752e4e117 9 minutes ago 188.3 MB
|
||||||
|
image3 latest 511136ea3c5a 25 minutes ago 188.3 MB
|
||||||
|
|
||||||
|
#### Since
|
||||||
|
|
||||||
|
The `since` filter shows only images created after the image with
|
||||||
|
given id or reference. For example, having these images:
|
||||||
|
|
||||||
|
$ docker images
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
image1 latest eeae25ada2aa 4 minutes ago 188.3 MB
|
||||||
|
image2 latest dea752e4e117 9 minutes ago 188.3 MB
|
||||||
|
image3 latest 511136ea3c5a 25 minutes ago 188.3 MB
|
||||||
|
|
||||||
|
Filtering with `since` would give:
|
||||||
|
|
||||||
|
$ docker images --filter "since=image3"
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
image1 latest eeae25ada2aa 4 minutes ago 188.3 MB
|
||||||
|
image2 latest dea752e4e117 9 minutes ago 188.3 MB
|
||||||
|
|
||||||
|
|
||||||
## Formatting
|
## Formatting
|
||||||
|
|
||||||
The formatting option (`--format`) will pretty print container output
|
The formatting option (`--format`) will pretty print container output
|
||||||
|
|
|
@ -121,6 +121,75 @@ func (s *DockerSuite) TestImagesFilterLabelWithCommit(c *check.C) {
|
||||||
c.Assert(out, check.Equals, imageID)
|
c.Assert(out, check.Equals, imageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestImagesFilterSinceAndBefore(c *check.C) {
|
||||||
|
imageID1, err := buildImage("image:1", `FROM `+minimalBaseImage()+`
|
||||||
|
LABEL number=1`, true)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
imageID2, err := buildImage("image:2", `FROM `+minimalBaseImage()+`
|
||||||
|
LABEL number=2`, true)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
imageID3, err := buildImage("image:3", `FROM `+minimalBaseImage()+`
|
||||||
|
LABEL number=3`, true)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
expected := []string{imageID3, imageID2}
|
||||||
|
|
||||||
|
out, _ := dockerCmd(c, "images", "-f", "since=image:1", "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "images", "-f", "since="+imageID1, "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
|
||||||
|
expected = []string{imageID3}
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "images", "-f", "since=image:2", "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "images", "-f", "since="+imageID2, "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
|
||||||
|
expected = []string{imageID2, imageID1}
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "images", "-f", "before=image:3", "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "images", "-f", "before="+imageID3, "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
|
||||||
|
expected = []string{imageID1}
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "images", "-f", "before=image:2", "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
|
||||||
|
out, _ = dockerCmd(c, "images", "-f", "before="+imageID2, "image")
|
||||||
|
c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out))
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertImageList(out string, expected []string) bool {
|
||||||
|
lines := strings.Split(strings.Trim(out, "\n "), "\n")
|
||||||
|
|
||||||
|
if len(lines)-1 != len(expected) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
imageIDIndex := strings.Index(lines[0], "IMAGE ID")
|
||||||
|
for i := 0; i < len(expected); i++ {
|
||||||
|
imageID := lines[i+1][imageIDIndex : imageIDIndex+12]
|
||||||
|
found := false
|
||||||
|
for _, e := range expected {
|
||||||
|
if imageID == e[7:19] {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) {
|
func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) {
|
||||||
testRequires(c, DaemonIsLinux)
|
testRequires(c, DaemonIsLinux)
|
||||||
imageName := "images_filter_test"
|
imageName := "images_filter_test"
|
||||||
|
|
|
@ -38,7 +38,11 @@ versions.
|
||||||
Show image digests. The default is *false*.
|
Show image digests. The default is *false*.
|
||||||
|
|
||||||
**-f**, **--filter**=[]
|
**-f**, **--filter**=[]
|
||||||
Filters the output. The dangling=true filter finds unused images. While label=com.foo=amd64 filters for images with a com.foo value of amd64. The label=com.foo filter finds images with the label com.foo of any value.
|
Filters the output based on these conditions:
|
||||||
|
- dangling=(true|false) - finds unused images.
|
||||||
|
- label=<key> or label=<key>=<value>
|
||||||
|
- before=(<image-name>[:tag]|<image-id>|<image@digest>)
|
||||||
|
- since=(<image-name>[:tag]|<image-id>|<image@digest>)
|
||||||
|
|
||||||
**--format**="*TEMPLATE*"
|
**--format**="*TEMPLATE*"
|
||||||
Pretty-print containers using a Go template.
|
Pretty-print containers using a Go template.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче