From ec22a1e5b2deaa48a07ccbc0fb4d4501928834ca Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Tue, 28 Oct 2025 18:26:08 -0500 Subject: [PATCH] client: refactor `ContainerTop` to wrap options and results Signed-off-by: Austin Vazquez --- client/client_interfaces.go | 2 +- client/container_top.go | 23 ++++++++++++++----- client/container_top_test.go | 10 ++++---- integration-cli/docker_api_containers_test.go | 4 ++-- .../moby/moby/client/client_interfaces.go | 2 +- .../moby/moby/client/container_top.go | 23 ++++++++++++++----- 6 files changed, 44 insertions(+), 20 deletions(-) diff --git a/client/client_interfaces.go b/client/client_interfaces.go index d6e6e855f0..8433c728ed 100644 --- a/client/client_interfaces.go +++ b/client/client_interfaces.go @@ -73,7 +73,7 @@ type ContainerAPIClient interface { ContainerStats(ctx context.Context, container string, options ContainerStatsOptions) (ContainerStatsResult, error) ContainerStart(ctx context.Context, container string, options ContainerStartOptions) (ContainerStartResult, error) ContainerStop(ctx context.Context, container string, options ContainerStopOptions) (ContainerStopResult, error) - ContainerTop(ctx context.Context, container string, arguments []string) (container.TopResponse, error) + ContainerTop(ctx context.Context, container string, options ContainerTopOptions) (ContainerTopResult, error) ContainerUnpause(ctx context.Context, container string, options ContainerUnPauseOptions) (ContainerUnPauseResult, error) ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) diff --git a/client/container_top.go b/client/container_top.go index 96b7e87f3d..dc0af8ae48 100644 --- a/client/container_top.go +++ b/client/container_top.go @@ -9,25 +9,36 @@ import ( "github.com/moby/moby/api/types/container" ) +// ContainerTopOptions defines options for container top operations. +type ContainerTopOptions struct { + Arguments []string +} + +// ContainerTopResult represents the result of a ContainerTop operation. +type ContainerTopResult struct { + Processes [][]string + Titles []string +} + // ContainerTop shows process information from within a container. -func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (container.TopResponse, error) { +func (cli *Client) ContainerTop(ctx context.Context, containerID string, options ContainerTopOptions) (ContainerTopResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.TopResponse{}, err + return ContainerTopResult{}, err } query := url.Values{} - if len(arguments) > 0 { - query.Set("ps_args", strings.Join(arguments, " ")) + if len(options.Arguments) > 0 { + query.Set("ps_args", strings.Join(options.Arguments, " ")) } resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) defer ensureReaderClosed(resp) if err != nil { - return container.TopResponse{}, err + return ContainerTopResult{}, err } var response container.TopResponse err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerTopResult{Processes: response.Processes, Titles: response.Titles}, err } diff --git a/client/container_top_test.go b/client/container_top_test.go index 82616915d6..aa12f31483 100644 --- a/client/container_top_test.go +++ b/client/container_top_test.go @@ -15,14 +15,14 @@ import ( func TestContainerTopError(t *testing.T) { client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error"))) assert.NilError(t, err) - _, err = client.ContainerTop(context.Background(), "nothing", []string{}) + _, err = client.ContainerTop(context.Background(), "nothing", ContainerTopOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal)) - _, err = client.ContainerTop(context.Background(), "", []string{}) + _, err = client.ContainerTop(context.Background(), "", ContainerTopOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) - _, err = client.ContainerTop(context.Background(), " ", []string{}) + _, err = client.ContainerTop(context.Background(), " ", ContainerTopOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) } @@ -54,7 +54,9 @@ func TestContainerTop(t *testing.T) { })) assert.NilError(t, err) - processList, err := client.ContainerTop(context.Background(), "container_id", []string{"arg1", "arg2"}) + processList, err := client.ContainerTop(context.Background(), "container_id", ContainerTopOptions{ + Arguments: []string{"arg1", "arg2"}, + }) assert.NilError(t, err) assert.Check(t, is.DeepEqual(expectedProcesses, processList.Processes)) assert.Check(t, is.DeepEqual(expectedTitles, processList.Titles)) diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 5441e28e78..1dc6a41b40 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -393,7 +393,7 @@ func (s *DockerAPISuite) TestContainerAPITop(c *testing.T) { defer apiClient.Close() // sort by comm[andline] to make sure order stays the same in case of PID rollover - top, err := apiClient.ContainerTop(testutil.GetContext(c), id, []string{"aux", "--sort=comm"}) + top, err := apiClient.ContainerTop(testutil.GetContext(c), id, client.ContainerTopOptions{Arguments: []string{"aux", "--sort=comm"}}) assert.NilError(c, err) assert.Equal(c, len(top.Titles), 11, fmt.Sprintf("expected 11 titles, found %d: %v", len(top.Titles), top.Titles)) @@ -414,7 +414,7 @@ func (s *DockerAPISuite) TestContainerAPITopWindows(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - top, err := apiClient.ContainerTop(testutil.GetContext(c), id, nil) + top, err := apiClient.ContainerTop(testutil.GetContext(c), id, client.ContainerTopOptions{}) assert.NilError(c, err) assert.Equal(c, len(top.Titles), 4, "expected 4 titles, found %d: %v", len(top.Titles), top.Titles) diff --git a/vendor/github.com/moby/moby/client/client_interfaces.go b/vendor/github.com/moby/moby/client/client_interfaces.go index d6e6e855f0..8433c728ed 100644 --- a/vendor/github.com/moby/moby/client/client_interfaces.go +++ b/vendor/github.com/moby/moby/client/client_interfaces.go @@ -73,7 +73,7 @@ type ContainerAPIClient interface { ContainerStats(ctx context.Context, container string, options ContainerStatsOptions) (ContainerStatsResult, error) ContainerStart(ctx context.Context, container string, options ContainerStartOptions) (ContainerStartResult, error) ContainerStop(ctx context.Context, container string, options ContainerStopOptions) (ContainerStopResult, error) - ContainerTop(ctx context.Context, container string, arguments []string) (container.TopResponse, error) + ContainerTop(ctx context.Context, container string, options ContainerTopOptions) (ContainerTopResult, error) ContainerUnpause(ctx context.Context, container string, options ContainerUnPauseOptions) (ContainerUnPauseResult, error) ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) diff --git a/vendor/github.com/moby/moby/client/container_top.go b/vendor/github.com/moby/moby/client/container_top.go index 96b7e87f3d..dc0af8ae48 100644 --- a/vendor/github.com/moby/moby/client/container_top.go +++ b/vendor/github.com/moby/moby/client/container_top.go @@ -9,25 +9,36 @@ import ( "github.com/moby/moby/api/types/container" ) +// ContainerTopOptions defines options for container top operations. +type ContainerTopOptions struct { + Arguments []string +} + +// ContainerTopResult represents the result of a ContainerTop operation. +type ContainerTopResult struct { + Processes [][]string + Titles []string +} + // ContainerTop shows process information from within a container. -func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (container.TopResponse, error) { +func (cli *Client) ContainerTop(ctx context.Context, containerID string, options ContainerTopOptions) (ContainerTopResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.TopResponse{}, err + return ContainerTopResult{}, err } query := url.Values{} - if len(arguments) > 0 { - query.Set("ps_args", strings.Join(arguments, " ")) + if len(options.Arguments) > 0 { + query.Set("ps_args", strings.Join(options.Arguments, " ")) } resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) defer ensureReaderClosed(resp) if err != nil { - return container.TopResponse{}, err + return ContainerTopResult{}, err } var response container.TopResponse err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerTopResult{Processes: response.Processes, Titles: response.Titles}, err }