client/image_list: Wrap options and result

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
This commit is contained in:
Paweł Gronowski
2025-10-20 17:28:21 +02:00
committed by Austin Vazquez
parent a7f409014f
commit b3974f07f5
15 changed files with 61 additions and 47 deletions

View File

@@ -111,7 +111,7 @@ type ImageAPIClient interface {
ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (ImageCreateResult, error)
ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (ImageImportResult, error)
ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error)
ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error)
ImagePull(ctx context.Context, ref string, options ImagePullOptions) (ImagePullResponse, error)
ImagePush(ctx context.Context, ref string, options ImagePushOptions) (ImagePushResponse, error)
ImageRemove(ctx context.Context, image string, options ImageRemoveOptions) ([]image.DeleteResponse, error)

View File

@@ -15,7 +15,7 @@ import (
// to include [image.Summary.Manifests] with information about image manifests.
// This is experimental and might change in the future without any backward
// compatibility.
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error) {
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error) {
var images []image.Summary
query := url.Values{}
@@ -34,7 +34,7 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
if err := cli.checkVersion(ctx); err != nil {
return images, err
return ImageListResult{}, err
}
if versions.GreaterThanOrEqualTo(cli.version, "1.47") {
@@ -45,9 +45,9 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
resp, err := cli.get(ctx, "/images/json", query, nil)
defer ensureReaderClosed(resp)
if err != nil {
return images, err
return ImageListResult{}, err
}
err = json.NewDecoder(resp.Body).Decode(&images)
return images, err
return ImageListResult{Items: images}, err
}

View File

@@ -1,5 +1,7 @@
package client
import "github.com/moby/moby/api/types/image"
// ImageListOptions holds parameters to list images with.
type ImageListOptions struct {
// All controls whether all images in the graph are filtered, or just
@@ -15,3 +17,8 @@ type ImageListOptions struct {
// Manifests indicates whether the image manifests should be returned.
Manifests bool
}
// ImageListResult holds the result from ImageList.
type ImageListResult struct {
Items []image.Summary
}

View File

@@ -108,7 +108,7 @@ func TestImageList(t *testing.T) {
images, err := client.ImageList(context.Background(), listCase.options)
assert.NilError(t, err)
assert.Check(t, is.Len(images, 2))
assert.Check(t, is.Len(images.Items, 2))
}
}

View File

@@ -102,10 +102,10 @@ func (s *DockerAPISuite) TestAPIImagesSizeCompatibility(c *testing.T) {
apiclient := testEnv.APIClient()
defer apiclient.Close()
images, err := apiclient.ImageList(testutil.GetContext(c), client.ImageListOptions{})
imageList, err := apiclient.ImageList(testutil.GetContext(c), client.ImageListOptions{})
assert.NilError(c, err)
assert.Assert(c, len(images) != 0)
for _, img := range images {
assert.Assert(c, len(imageList.Items) != 0)
for _, img := range imageList.Items {
assert.Assert(c, img.Size != int64(-1))
}
@@ -115,8 +115,8 @@ func (s *DockerAPISuite) TestAPIImagesSizeCompatibility(c *testing.T) {
v124Images, err := apiclient.ImageList(testutil.GetContext(c), client.ImageListOptions{})
assert.NilError(c, err)
assert.Assert(c, len(v124Images) != 0)
for _, img := range v124Images {
assert.Assert(c, len(v124Images.Items) != 0)
for _, img := range v124Images.Items {
assert.Assert(c, img.Size != int64(-1))
}
}

View File

@@ -47,7 +47,7 @@ func TestExportContainerAndImportImage(t *testing.T) {
Filters: make(client.Filters).Add("reference", reference),
})
assert.NilError(t, err)
assert.Check(t, is.Equal(jm.Status, images.Images[0].ID))
assert.Check(t, is.Equal(jm.Status, images.Items[0].ID))
}
// TestExportContainerAfterDaemonRestart checks that a container

View File

@@ -136,7 +136,7 @@ func TestMigrateSaveLoad(t *testing.T) {
// Delete all images
list, err := apiClient.ImageList(ctx, client.ImageListOptions{})
assert.NilError(t, err)
for _, i := range list {
for _, i := range list.Items {
_, err = apiClient.ImageRemove(ctx, i.ID, client.ImageRemoveOptions{Force: true})
assert.NilError(t, err)
}

View File

@@ -43,12 +43,12 @@ func TestImagesFilterMultiReference(t *testing.T) {
options := client.ImageListOptions{
Filters: make(client.Filters).Add("reference", repoTags[:3]...),
}
images, err := apiClient.ImageList(ctx, options)
imageList, err := apiClient.ImageList(ctx, options)
assert.NilError(t, err)
assert.Assert(t, is.Len(images, 1))
assert.Check(t, is.Len(images[0].RepoTags, 3))
for _, repoTag := range images[0].RepoTags {
assert.Assert(t, is.Len(imageList.Items, 1))
assert.Check(t, is.Len(imageList.Items[0].RepoTags, 3))
for _, repoTag := range imageList.Items[0].RepoTags {
if repoTag != repoTags[0] && repoTag != repoTags[1] && repoTag != repoTags[2] {
t.Errorf("list images doesn't match any repoTag we expected, repoTag: %s", repoTag)
}
@@ -91,7 +91,7 @@ func TestImagesFilterUntil(t *testing.T) {
assert.NilError(t, err)
var listedIDs []string
for _, i := range list {
for _, i := range list.Items {
t.Logf("ImageList: ID=%v RepoTags=%v", i.ID, i.RepoTags)
listedIDs = append(listedIDs, i.ID)
}
@@ -124,7 +124,7 @@ func TestImagesFilterBeforeSince(t *testing.T) {
assert.NilError(t, err)
var listedIDs []string
for _, i := range list {
for _, i := range list.Items {
t.Logf("ImageList: ID=%v RepoTags=%v", i.ID, i.RepoTags)
listedIDs = append(listedIDs, i.ID)
}
@@ -181,12 +181,12 @@ func TestAPIImagesFilters(t *testing.T) {
t.Parallel()
ctx := testutil.StartSpan(ctx, t)
images, err := apiClient.ImageList(ctx, client.ImageListOptions{
imageList, err := apiClient.ImageList(ctx, client.ImageListOptions{
Filters: tc.filters,
})
assert.Check(t, err)
assert.Assert(t, is.Len(images, tc.expectedImages))
assert.Check(t, is.Len(images[0].RepoTags, tc.expectedRepoTags))
assert.Assert(t, is.Len(imageList.Items, tc.expectedImages))
assert.Check(t, is.Len(imageList.Items[0].RepoTags, tc.expectedRepoTags))
})
}
}
@@ -255,31 +255,31 @@ func TestAPIImagesListManifests(t *testing.T) {
// TODO: Remove when MinAPIVersion >= 1.47
c := d.NewClientT(t, client.WithVersion("1.46"))
images, err := c.ImageList(ctx, client.ImageListOptions{Manifests: true})
imageList, err := c.ImageList(ctx, client.ImageListOptions{Manifests: true})
assert.NilError(t, err)
assert.Assert(t, is.Len(images, 1))
assert.Check(t, is.Nil(images[0].Manifests))
assert.Assert(t, is.Len(imageList.Items, 1))
assert.Check(t, is.Nil(imageList.Items[0].Manifests))
})
api147 := d.NewClientT(t, client.WithVersion("1.47"))
t.Run("no manifests if not requested", func(t *testing.T) {
images, err := api147.ImageList(ctx, client.ImageListOptions{})
imageList, err := api147.ImageList(ctx, client.ImageListOptions{})
assert.NilError(t, err)
assert.Assert(t, is.Len(images, 1))
assert.Check(t, is.Nil(images[0].Manifests))
assert.Assert(t, is.Len(imageList.Items, 1))
assert.Check(t, is.Nil(imageList.Items[0].Manifests))
})
images, err := api147.ImageList(ctx, client.ImageListOptions{Manifests: true})
imageList, err := api147.ImageList(ctx, client.ImageListOptions{Manifests: true})
assert.NilError(t, err)
assert.Check(t, is.Len(images, 1))
assert.Check(t, images[0].Manifests != nil)
assert.Check(t, is.Len(images[0].Manifests, 3))
assert.Check(t, is.Len(imageList.Items, 1))
assert.Check(t, imageList.Items[0].Manifests != nil)
assert.Check(t, is.Len(imageList.Items[0].Manifests, 3))
for _, mfst := range images[0].Manifests {
for _, mfst := range imageList.Items[0].Manifests {
// All manifests should be image manifests
assert.Check(t, is.Equal(mfst.Kind, image.ManifestKindImage))

View File

@@ -29,7 +29,7 @@ func TestLoadDanglingImages(t *testing.T) {
})
// Should be one image.
images, err := apiClient.ImageList(ctx, client.ImageListOptions{})
imageList, err := apiClient.ImageList(ctx, client.ImageListOptions{})
assert.NilError(t, err)
findImageByName := func(images []image.Summary, imageName string) (image.Summary, error) {
@@ -42,7 +42,7 @@ func TestLoadDanglingImages(t *testing.T) {
return images[index], nil
}
oldImage, err := findImageByName(images, "namedimage:latest")
oldImage, err := findImageByName(imageList.Items, "namedimage:latest")
assert.NilError(t, err)
// Retain a copy of the old image and then replace it with a new one.
@@ -52,10 +52,10 @@ func TestLoadDanglingImages(t *testing.T) {
})
})
images, err = apiClient.ImageList(ctx, client.ImageListOptions{})
imageList, err = apiClient.ImageList(ctx, client.ImageListOptions{})
assert.NilError(t, err)
newImage, err := findImageByName(images, "namedimage:latest")
newImage, err := findImageByName(imageList.Items, "namedimage:latest")
assert.NilError(t, err)
// IDs should be different.
@@ -72,7 +72,7 @@ func TestLoadDanglingImages(t *testing.T) {
return images[index], nil
}
danglingImage, err := findImageById(images, oldImage.ID)
danglingImage, err := findImageById(imageList.Items, oldImage.ID)
assert.NilError(t, err)
assert.Check(t, is.Len(danglingImage.RepoTags, 0))
}

View File

@@ -94,10 +94,10 @@ func getAllContainers(ctx context.Context, t testing.TB, apiClient client.Contai
func deleteAllImages(ctx context.Context, t testing.TB, apiclient client.ImageAPIClient, protectedImages map[string]struct{}) {
t.Helper()
images, err := apiclient.ImageList(ctx, client.ImageListOptions{})
imageList, err := apiclient.ImageList(ctx, client.ImageListOptions{})
assert.Check(t, err, "failed to list images")
for _, img := range images {
for _, img := range imageList.Items {
tags := tagsFromImageSummary(img)
if _, ok := protectedImages[img.ID]; ok {
continue

View File

@@ -205,7 +205,7 @@ func (e *Execution) HasExistingImage(t testing.TB, reference string) bool {
})
assert.NilError(t, err, "failed to list images")
return len(imageList) > 0
return len(imageList.Items) > 0
}
// EnsureFrozenImagesLinux loads frozen test images into the daemon

View File

@@ -121,7 +121,7 @@ func getExistingImages(ctx context.Context, t testing.TB, testEnv *Execution) []
assert.NilError(t, err, "failed to list images")
var images []string
for _, img := range imageList {
for _, img := range imageList.Items {
images = append(images, tagsFromImageSummary(img)...)
}
return images

View File

@@ -111,7 +111,7 @@ type ImageAPIClient interface {
ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (ImageCreateResult, error)
ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (ImageImportResult, error)
ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error)
ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error)
ImagePull(ctx context.Context, ref string, options ImagePullOptions) (ImagePullResponse, error)
ImagePush(ctx context.Context, ref string, options ImagePushOptions) (ImagePushResponse, error)
ImageRemove(ctx context.Context, image string, options ImageRemoveOptions) ([]image.DeleteResponse, error)

View File

@@ -15,7 +15,7 @@ import (
// to include [image.Summary.Manifests] with information about image manifests.
// This is experimental and might change in the future without any backward
// compatibility.
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error) {
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error) {
var images []image.Summary
query := url.Values{}
@@ -34,7 +34,7 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
if err := cli.checkVersion(ctx); err != nil {
return images, err
return ImageListResult{}, err
}
if versions.GreaterThanOrEqualTo(cli.version, "1.47") {
@@ -45,9 +45,9 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
resp, err := cli.get(ctx, "/images/json", query, nil)
defer ensureReaderClosed(resp)
if err != nil {
return images, err
return ImageListResult{}, err
}
err = json.NewDecoder(resp.Body).Decode(&images)
return images, err
return ImageListResult{Items: images}, err
}

View File

@@ -1,5 +1,7 @@
package client
import "github.com/moby/moby/api/types/image"
// ImageListOptions holds parameters to list images with.
type ImageListOptions struct {
// All controls whether all images in the graph are filtered, or just
@@ -15,3 +17,8 @@ type ImageListOptions struct {
// Manifests indicates whether the image manifests should be returned.
Manifests bool
}
// ImageListResult holds the result from ImageList.
type ImageListResult struct {
Items []image.Summary
}