Merge pull request #44503 from corhere/image-ls-before-after-filters
List images with multiple since/before filters
This commit is contained in:
commit
186d3ba70e
2 changed files with 68 additions and 14 deletions
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
|
@ -46,20 +47,36 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions)
|
|||
}
|
||||
|
||||
var (
|
||||
beforeFilter, sinceFilter *image.Image
|
||||
beforeFilter, sinceFilter time.Time
|
||||
err error
|
||||
)
|
||||
err = opts.Filters.WalkValues("before", func(value string) error {
|
||||
beforeFilter, err = i.GetImage(ctx, value, imagetypes.GetImageOpts{})
|
||||
return err
|
||||
img, err := i.GetImage(ctx, value, imagetypes.GetImageOpts{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Resolve multiple values to the oldest image,
|
||||
// equivalent to ANDing all the values together.
|
||||
if beforeFilter.IsZero() || beforeFilter.After(img.Created) {
|
||||
beforeFilter = img.Created
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = opts.Filters.WalkValues("since", func(value string) error {
|
||||
sinceFilter, err = i.GetImage(ctx, value, imagetypes.GetImageOpts{})
|
||||
return err
|
||||
img, err := i.GetImage(ctx, value, imagetypes.GetImageOpts{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Resolve multiple values to the newest image,
|
||||
// equivalent to ANDing all the values together.
|
||||
if sinceFilter.Before(img.Created) {
|
||||
sinceFilter = img.Created
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -84,16 +101,11 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions)
|
|||
default:
|
||||
}
|
||||
|
||||
if beforeFilter != nil {
|
||||
if img.Created.Equal(beforeFilter.Created) || img.Created.After(beforeFilter.Created) {
|
||||
continue
|
||||
}
|
||||
if !beforeFilter.IsZero() && !img.Created.Before(beforeFilter) {
|
||||
continue
|
||||
}
|
||||
|
||||
if sinceFilter != nil {
|
||||
if img.Created.Equal(sinceFilter.Created) || img.Created.Before(sinceFilter.Created) {
|
||||
continue
|
||||
}
|
||||
if !sinceFilter.IsZero() && !img.Created.After(sinceFilter) {
|
||||
continue
|
||||
}
|
||||
|
||||
if opts.Filters.Contains("label") {
|
||||
|
|
|
@ -2,12 +2,16 @@ package image // import "github.com/docker/docker/integration/image"
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/skip"
|
||||
|
@ -51,3 +55,41 @@ func TestImagesFilterMultiReference(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImagesFilterBeforeSince(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := testEnv.APIClient()
|
||||
ctx := context.Background()
|
||||
|
||||
name := strings.ToLower(t.Name())
|
||||
ctr := container.Create(ctx, t, client, container.WithName(name))
|
||||
|
||||
imgs := make([]string, 5)
|
||||
for i := range imgs {
|
||||
if i > 0 {
|
||||
// Make really really sure each image has a distinct timestamp.
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
id, err := client.ContainerCommit(ctx, ctr, types.ContainerCommitOptions{Reference: fmt.Sprintf("%s:v%d", name, i)})
|
||||
assert.NilError(t, err)
|
||||
imgs[i] = id.ID
|
||||
}
|
||||
|
||||
filter := filters.NewArgs(
|
||||
filters.Arg("since", imgs[0]),
|
||||
filters.Arg("before", imgs[len(imgs)-1]),
|
||||
)
|
||||
list, err := client.ImageList(ctx, types.ImageListOptions{Filters: filter})
|
||||
assert.NilError(t, err)
|
||||
|
||||
var listedIDs []string
|
||||
for _, i := range list {
|
||||
t.Logf("ImageList: ID=%v RepoTags=%v", i.ID, i.RepoTags)
|
||||
listedIDs = append(listedIDs, i.ID)
|
||||
}
|
||||
// The ImageList API sorts the list by created timestamp... truncated to
|
||||
// 1-second precision. Since all the images were created within
|
||||
// milliseconds of each other, listedIDs is effectively unordered and
|
||||
// the assertion must therefore be order-independent.
|
||||
assert.DeepEqual(t, listedIDs, imgs[1:len(imgs)-1], cmpopts.SortSlices(func(a, b string) bool { return a < b }))
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue