Browse Source

Add until filter to docker image ls
Signed-off-by: Rachit Sharma <rachitsharma613@gmail.com>

add handling for multiple filters

Signed-off-by: Rachit Sharma <rachitsharma613@gmail.com>

Update integration/image/list_test.go

Co-authored-by: Cory Snider <corhere@gmail.com>
Signed-off-by: Rachit Sharma <rachitsharma613@gmail.com>

Add documentation of filter

Signed-off-by: Rachit Sharma <rachitsharma613@gmail.com>

Update integration/image/list_test.go

Co-authored-by: Cory Snider <corhere@gmail.com>
Signed-off-by: Rachit Sharma <rachitsharma613@gmail.com>

Fix bug with CommitOptions

Signed-off-by: Rachit Sharma <rachitsharma613@gmail.com>

add wrapping of text to 80 chars

Signed-off-by: Rachit Sharma <rachitsharma613@gmail.com>

Rachit Sharma 1 year ago
parent
commit
7995e3288f
4 changed files with 71 additions and 0 deletions
  1. 1 0
      api/swagger.yaml
  2. 21 0
      daemon/images/image_list.go
  3. 5 0
      docs/api/version-history.md
  4. 44 0
      integration/image/list_test.go

+ 1 - 0
api/swagger.yaml

@@ -8075,6 +8075,7 @@ paths:
             - `label=key` or `label="key=value"` of an image label
             - `label=key` or `label="key=value"` of an image label
             - `reference`=(`<image-name>[:<tag>]`)
             - `reference`=(`<image-name>[:<tag>]`)
             - `since`=(`<image-name>[:<tag>]`,  `<image id>` or `<image@digest>`)
             - `since`=(`<image-name>[:<tag>]`,  `<image id>` or `<image@digest>`)
+            - `until=<timestamp>`
           type: "string"
           type: "string"
         - name: "shared-size"
         - name: "shared-size"
           in: "query"
           in: "query"

+ 21 - 0
daemon/images/image_list.go

@@ -10,6 +10,7 @@ import (
 	"github.com/distribution/reference"
 	"github.com/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
 	imagetypes "github.com/docker/docker/api/types/image"
 	imagetypes "github.com/docker/docker/api/types/image"
+	timetypes "github.com/docker/docker/api/types/time"
 	"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"
@@ -21,6 +22,7 @@ var acceptedImageFilterTags = map[string]bool{
 	"before":    true,
 	"before":    true,
 	"since":     true,
 	"since":     true,
 	"reference": true,
 	"reference": true,
+	"until":     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
@@ -59,6 +61,25 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions)
 		return nil, err
 		return nil, err
 	}
 	}
 
 
+	err = opts.Filters.WalkValues("until", func(value string) error {
+		ts, err := timetypes.GetTimestamp(value, time.Now())
+		if err != nil {
+			return err
+		}
+		seconds, nanoseconds, err := timetypes.ParseTimestamps(ts, 0)
+		if err != nil {
+			return err
+		}
+		timestamp := time.Unix(seconds, nanoseconds)
+		if beforeFilter.IsZero() || beforeFilter.After(timestamp) {
+			beforeFilter = timestamp
+		}
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+
 	err = opts.Filters.WalkValues("since", func(value string) error {
 	err = opts.Filters.WalkValues("since", func(value string) error {
 		img, err := i.GetImage(ctx, value, imagetypes.GetImageOpts{})
 		img, err := i.GetImage(ctx, value, imagetypes.GetImageOpts{})
 		if err != nil {
 		if err != nil {

+ 5 - 0
docs/api/version-history.md

@@ -17,6 +17,11 @@ keywords: "API, Docker, rcli, REST, documentation"
 
 
 [Docker Engine API v1.44](https://docs.docker.com/engine/api/v1.44/) documentation
 [Docker Engine API v1.44](https://docs.docker.com/engine/api/v1.44/) documentation
 
 
+* GET `/images/json` now accepts an `until` filter. This accepts a timestamp and
+  lists all images created before it. The `<timestamp>` can be Unix timestamps,
+  date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`)
+  computed relative to the daemon machine’s time. This change is not versioned,
+  and affects all API versions if the daemon has this patch.
 * The `VirtualSize` field in the `GET /images/{name}/json`, `GET /images/json`,
 * The `VirtualSize` field in the `GET /images/{name}/json`, `GET /images/json`,
   and `GET /system/df` responses is now omitted. Use the `Size` field instead,
   and `GET /system/df` responses is now omitted. Use the `Size` field instead,
   which contains the same information.
   which contains the same information.

+ 44 - 0
integration/image/list_test.go

@@ -57,6 +57,50 @@ func TestImagesFilterMultiReference(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestImagesFilterUntil(t *testing.T) {
+	ctx := setupTest(t)
+
+	client := testEnv.APIClient()
+
+	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, containertypes.CommitOptions{Reference: fmt.Sprintf("%s:v%d", name, i)})
+		assert.NilError(t, err)
+		imgs[i] = id.ID
+	}
+
+	olderImage, _, err := client.ImageInspectWithRaw(ctx, imgs[2])
+	assert.NilError(t, err)
+	olderUntil := olderImage.Created
+
+	laterImage, _, err := client.ImageInspectWithRaw(ctx, imgs[3])
+	assert.NilError(t, err)
+	laterUntil := laterImage.Created
+
+	filter := filters.NewArgs(
+		filters.Arg("since", imgs[0]),
+		filters.Arg("until", olderUntil),
+		filters.Arg("until", laterUntil),
+		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)
+	}
+	assert.DeepEqual(t, listedIDs, imgs[1:2], cmpopts.SortSlices(func(a, b string) bool { return a < b }))
+}
+
 func TestImagesFilterBeforeSince(t *testing.T) {
 func TestImagesFilterBeforeSince(t *testing.T) {
 	ctx := setupTest(t)
 	ctx := setupTest(t)