From c6a45784f9a0d2b2ec31a30e45ffb784f609031b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 24 Oct 2025 11:55:05 +0200 Subject: [PATCH] client: VolumeListResult: define local type The `VolumeListResult.Items` field was a `volume.ListResponse`, which in itself also had two slices (for volumes, and warnings). The Volumes field contained a slice of pointers to Volumes. This patch: - Re-defines `ImageRemoveResult` as a distinct type, containing the content of the `volume.ListResponse.Volumes` and `.Warnings`. - The `VolumeListResult` doesn't use a pointer for the volumes to make it slightly easier to deal with (possibly the API type could be changed as well, which could allow us to simplify the client code. Signed-off-by: Sebastiaan van Stijn --- client/volume_list.go | 28 ++++++++++++++++--- client/volume_list_test.go | 2 +- integration/volume/volume_test.go | 9 +++--- internal/testutil/environment/clean.go | 2 +- internal/testutil/environment/protect.go | 2 +- .../moby/moby/client/volume_list.go | 28 ++++++++++++++++--- 6 files changed, 55 insertions(+), 16 deletions(-) diff --git a/client/volume_list.go b/client/volume_list.go index 0c5bd7e61b..802f104eaf 100644 --- a/client/volume_list.go +++ b/client/volume_list.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/url" + "slices" "github.com/moby/moby/api/types/volume" ) @@ -15,7 +16,11 @@ type VolumeListOptions struct { // VolumeListResult holds the result from the [Client.VolumeList] method. type VolumeListResult struct { - Items volume.ListResponse + // List of volumes. + Items []volume.Volume + + // Warnings that occurred when fetching the list of volumes. + Warnings []string } // VolumeList returns the volumes configured in the docker host. @@ -29,7 +34,22 @@ func (cli *Client) VolumeList(ctx context.Context, options VolumeListOptions) (V return VolumeListResult{}, err } - var res VolumeListResult - err = json.NewDecoder(resp.Body).Decode(&res.Items) - return res, err + var apiResp volume.ListResponse + err = json.NewDecoder(resp.Body).Decode(&apiResp) + if err != nil { + return VolumeListResult{}, err + } + + res := VolumeListResult{ + Items: make([]volume.Volume, 0, len(apiResp.Volumes)), + Warnings: slices.Clone(apiResp.Warnings), + } + + for _, vol := range apiResp.Volumes { + if vol != nil { + res.Items = append(res.Items, *vol) + } + } + + return res, nil } diff --git a/client/volume_list_test.go b/client/volume_list_test.go index fd3e019b5c..3fa019ce9c 100644 --- a/client/volume_list_test.go +++ b/client/volume_list_test.go @@ -64,6 +64,6 @@ func TestVolumeList(t *testing.T) { result, err := client.VolumeList(context.Background(), VolumeListOptions{Filters: listCase.filters}) assert.NilError(t, err) - assert.Check(t, is.Len(result.Items.Volumes, 1)) + assert.Check(t, is.Len(result.Items, 1)) } } diff --git a/integration/volume/volume_test.go b/integration/volume/volume_test.go index 1987089e41..01ebead3d5 100644 --- a/integration/volume/volume_test.go +++ b/integration/volume/volume_test.go @@ -50,18 +50,17 @@ func TestVolumesCreateAndList(t *testing.T) { res, err := apiClient.VolumeList(ctx, client.VolumeListOptions{}) assert.NilError(t, err) - assert.Assert(t, len(res.Items.Volumes) > 0) + assert.Assert(t, len(res.Items) > 0) - volumes := res.Items.Volumes[:0] - for _, v := range res.Items.Volumes { + volumes := res.Items[:0] + for _, v := range res.Items { if v.Name == namedV.Name { volumes = append(volumes, v) } } assert.Check(t, is.Equal(len(volumes), 1)) - assert.Check(t, volumes[0] != nil) - assert.Check(t, is.DeepEqual(*volumes[0], expected, cmpopts.EquateEmpty())) + assert.Check(t, is.DeepEqual(volumes[0], expected, cmpopts.EquateEmpty())) } func TestVolumesRemove(t *testing.T) { diff --git a/internal/testutil/environment/clean.go b/internal/testutil/environment/clean.go index cef84930e8..7affbaab09 100644 --- a/internal/testutil/environment/clean.go +++ b/internal/testutil/environment/clean.go @@ -130,7 +130,7 @@ func deleteAllVolumes(ctx context.Context, t testing.TB, c client.VolumeAPIClien res, err := c.VolumeList(ctx, client.VolumeListOptions{}) assert.Check(t, err, "failed to list volumes") - for _, v := range res.Items.Volumes { + for _, v := range res.Items { if _, ok := protectedVolumes[v.Name]; ok { continue } diff --git a/internal/testutil/environment/protect.go b/internal/testutil/environment/protect.go index f683ac287a..784727ab9a 100644 --- a/internal/testutil/environment/protect.go +++ b/internal/testutil/environment/protect.go @@ -231,7 +231,7 @@ func getExistingVolumes(ctx context.Context, t testing.TB, testEnv *Execution) [ assert.NilError(t, err, "failed to list volumes") var volumes []string - for _, vol := range res.Items.Volumes { + for _, vol := range res.Items { volumes = append(volumes, vol.Name) } return volumes diff --git a/vendor/github.com/moby/moby/client/volume_list.go b/vendor/github.com/moby/moby/client/volume_list.go index 0c5bd7e61b..802f104eaf 100644 --- a/vendor/github.com/moby/moby/client/volume_list.go +++ b/vendor/github.com/moby/moby/client/volume_list.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/url" + "slices" "github.com/moby/moby/api/types/volume" ) @@ -15,7 +16,11 @@ type VolumeListOptions struct { // VolumeListResult holds the result from the [Client.VolumeList] method. type VolumeListResult struct { - Items volume.ListResponse + // List of volumes. + Items []volume.Volume + + // Warnings that occurred when fetching the list of volumes. + Warnings []string } // VolumeList returns the volumes configured in the docker host. @@ -29,7 +34,22 @@ func (cli *Client) VolumeList(ctx context.Context, options VolumeListOptions) (V return VolumeListResult{}, err } - var res VolumeListResult - err = json.NewDecoder(resp.Body).Decode(&res.Items) - return res, err + var apiResp volume.ListResponse + err = json.NewDecoder(resp.Body).Decode(&apiResp) + if err != nil { + return VolumeListResult{}, err + } + + res := VolumeListResult{ + Items: make([]volume.Volume, 0, len(apiResp.Volumes)), + Warnings: slices.Clone(apiResp.Warnings), + } + + for _, vol := range apiResp.Volumes { + if vol != nil { + res.Items = append(res.Items, *vol) + } + } + + return res, nil }