diff --git a/client/client_interfaces.go b/client/client_interfaces.go index fcb00553fc..e3359ffbda 100644 --- a/client/client_interfaces.go +++ b/client/client_interfaces.go @@ -168,8 +168,8 @@ type ServiceAPIClient interface { ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) ServiceLogs(ctx context.Context, serviceID string, options ContainerLogsOptions) (io.ReadCloser, error) TaskLogs(ctx context.Context, taskID string, options ContainerLogsOptions) (io.ReadCloser, error) - TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) - TaskList(ctx context.Context, options TaskListOptions) ([]swarm.Task, error) + TaskInspect(ctx context.Context, taskID string) (TaskInspectResult, error) + TaskList(ctx context.Context, options TaskListOptions) (TaskListResult, error) } // SwarmAPIClient defines API client methods for the swarm diff --git a/client/swarm_task_list_opts.go b/client/swarm_task_list_opts.go deleted file mode 100644 index d33f38e1e4..0000000000 --- a/client/swarm_task_list_opts.go +++ /dev/null @@ -1,6 +0,0 @@ -package client - -// TaskListOptions holds parameters to list tasks with. -type TaskListOptions struct { - Filters Filters -} diff --git a/client/task_inspect.go b/client/task_inspect.go index f38392d4e6..6012fe8a48 100644 --- a/client/task_inspect.go +++ b/client/task_inspect.go @@ -1,34 +1,31 @@ package client import ( - "bytes" "context" - "encoding/json" - "io" "github.com/moby/moby/api/types/swarm" ) -// TaskInspectWithRaw returns the task information and its raw representation. -func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { +// TaskInspectResult contains the result of a task inspection. +type TaskInspectResult struct { + Task swarm.Task + Raw []byte +} + +// TaskInspect returns the task information and its raw representation. +func (cli *Client) TaskInspect(ctx context.Context, taskID string) (TaskInspectResult, error) { taskID, err := trimID("task", taskID) if err != nil { - return swarm.Task{}, nil, err + return TaskInspectResult{}, err } resp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) defer ensureReaderClosed(resp) if err != nil { - return swarm.Task{}, nil, err + return TaskInspectResult{}, err } - body, err := io.ReadAll(resp.Body) - if err != nil { - return swarm.Task{}, nil, err - } - - var response swarm.Task - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err + var out TaskInspectResult + out.Raw, err = decodeWithRaw(resp, &out.Task) + return out, err } diff --git a/client/task_inspect_test.go b/client/task_inspect_test.go index 5c4174ccce..6a3a43742e 100644 --- a/client/task_inspect_test.go +++ b/client/task_inspect_test.go @@ -19,7 +19,7 @@ func TestTaskInspectError(t *testing.T) { client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error"))) assert.NilError(t, err) - _, _, err = client.TaskInspectWithRaw(context.Background(), "nothing") + _, err = client.TaskInspect(context.Background(), "nothing") assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal)) } @@ -28,11 +28,11 @@ func TestTaskInspectWithEmptyID(t *testing.T) { return nil, errors.New("should not make request") })) assert.NilError(t, err) - _, _, err = client.TaskInspectWithRaw(context.Background(), "") + _, err = client.TaskInspect(context.Background(), "") assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) - _, _, err = client.TaskInspectWithRaw(context.Background(), " ") + _, err = client.TaskInspect(context.Background(), " ") assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) } @@ -56,7 +56,7 @@ func TestTaskInspect(t *testing.T) { })) assert.NilError(t, err) - taskInspect, _, err := client.TaskInspectWithRaw(context.Background(), "task_id") + result, err := client.TaskInspect(context.Background(), "task_id") assert.NilError(t, err) - assert.Check(t, is.Equal(taskInspect.ID, "task_id")) + assert.Check(t, is.Equal(result.Task.ID, "task_id")) } diff --git a/client/task_list.go b/client/task_list.go index bea82ad1bf..0511c1c735 100644 --- a/client/task_list.go +++ b/client/task_list.go @@ -8,8 +8,18 @@ import ( "github.com/moby/moby/api/types/swarm" ) +// TaskListOptions holds parameters to list tasks with. +type TaskListOptions struct { + Filters Filters +} + +// TaskListResult contains the result of a task list operation. +type TaskListResult struct { + Tasks []swarm.Task +} + // TaskList returns the list of tasks. -func (cli *Client) TaskList(ctx context.Context, options TaskListOptions) ([]swarm.Task, error) { +func (cli *Client) TaskList(ctx context.Context, options TaskListOptions) (TaskListResult, error) { query := url.Values{} options.Filters.updateURLValues(query) @@ -17,10 +27,10 @@ func (cli *Client) TaskList(ctx context.Context, options TaskListOptions) ([]swa resp, err := cli.get(ctx, "/tasks", query, nil) defer ensureReaderClosed(resp) if err != nil { - return nil, err + return TaskListResult{}, err } var tasks []swarm.Task err = json.NewDecoder(resp.Body).Decode(&tasks) - return tasks, err + return TaskListResult{Tasks: tasks}, err } diff --git a/client/task_list_test.go b/client/task_list_test.go index 23b90a957a..0c7ec27d97 100644 --- a/client/task_list_test.go +++ b/client/task_list_test.go @@ -75,8 +75,8 @@ func TestTaskList(t *testing.T) { })) assert.NilError(t, err) - tasks, err := client.TaskList(context.Background(), listCase.options) + result, err := client.TaskList(context.Background(), listCase.options) assert.NilError(t, err) - assert.Check(t, is.Len(tasks, 2)) + assert.Check(t, is.Len(result.Tasks, 2)) } } diff --git a/integration-cli/daemon/daemon_swarm.go b/integration-cli/daemon/daemon_swarm.go index ffdf73f094..e12276885d 100644 --- a/integration-cli/daemon/daemon_swarm.go +++ b/integration-cli/daemon/daemon_swarm.go @@ -103,13 +103,13 @@ func (d *Daemon) CheckRunningTaskNetworks(ctx context.Context) func(t *testing.T cli := d.NewClientT(t) defer cli.Close() - tasks, err := cli.TaskList(ctx, client.TaskListOptions{ + taskResult, err := cli.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("desired-state", "running"), }) assert.NilError(t, err) result := make(map[string]int) - for _, task := range tasks { + for _, task := range taskResult.Tasks { for _, network := range task.Spec.Networks { result[network.Target]++ } @@ -124,13 +124,13 @@ func (d *Daemon) CheckRunningTaskImages(ctx context.Context) func(t *testing.T) cli := d.NewClientT(t) defer cli.Close() - tasks, err := cli.TaskList(ctx, client.TaskListOptions{ + taskResult, err := cli.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("desired-state", "running"), }) assert.NilError(t, err) result := make(map[string]int) - for _, task := range tasks { + for _, task := range taskResult.Tasks { if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil { result[task.Spec.ContainerSpec.Image]++ } diff --git a/integration/internal/swarm/service.go b/integration/internal/swarm/service.go index 614e93ef6f..b2c3a51139 100644 --- a/integration/internal/swarm/service.go +++ b/integration/internal/swarm/service.go @@ -204,14 +204,14 @@ func ServiceWithPidsLimit(limit int64) ServiceSpecOpt { func GetRunningTasks(ctx context.Context, t *testing.T, c client.ServiceAPIClient, serviceID string) []swarmtypes.Task { t.Helper() - tasks, err := c.TaskList(ctx, client.TaskListOptions{ + result, err := c.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters). Add("service", serviceID). Add("desired-state", "running"), }) assert.NilError(t, err) - return tasks + return result.Tasks } // ExecTask runs the passed in exec config on the given task diff --git a/integration/internal/swarm/states.go b/integration/internal/swarm/states.go index b00b87d71b..f5af4d23cd 100644 --- a/integration/internal/swarm/states.go +++ b/integration/internal/swarm/states.go @@ -12,15 +12,15 @@ import ( // NoTasksForService verifies that there are no more tasks for the given service func NoTasksForService(ctx context.Context, apiClient client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { - tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{ + result, err := apiClient.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("service", serviceID), }) if err == nil { - if len(tasks) == 0 { + if len(result.Tasks) == 0 { return poll.Success() } - if len(tasks) > 0 { - return poll.Continue("task count for service %s at %d waiting for 0", serviceID, len(tasks)) + if len(result.Tasks) > 0 { + return poll.Continue("task count for service %s at %d waiting for 0", serviceID, len(result.Tasks)) } return poll.Continue("waiting for tasks for service %s to be deleted", serviceID) } @@ -32,14 +32,14 @@ func NoTasksForService(ctx context.Context, apiClient client.ServiceAPIClient, s // NoTasks verifies that all tasks are gone func NoTasks(ctx context.Context, apiClient client.ServiceAPIClient) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { - tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{}) + result, err := apiClient.TaskList(ctx, client.TaskListOptions{}) switch { case err != nil: return poll.Error(err) - case len(tasks) == 0: + case len(result.Tasks) == 0: return poll.Success() default: - return poll.Continue("waiting for all tasks to be removed: task count at %d", len(tasks)) + return poll.Continue("waiting for all tasks to be removed: task count at %d", len(result.Tasks)) } } } @@ -47,12 +47,12 @@ func NoTasks(ctx context.Context, apiClient client.ServiceAPIClient) func(log po // RunningTasksCount verifies there are `instances` tasks running for `serviceID` func RunningTasksCount(ctx context.Context, apiClient client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { - tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{ + result, err := apiClient.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("service", serviceID), }) var running int var taskError string - for _, task := range tasks { + for _, task := range result.Tasks { switch task.Status.State { case swarmtypes.TaskStateRunning: running++ @@ -76,7 +76,7 @@ func RunningTasksCount(ctx context.Context, apiClient client.ServiceAPIClient, s case running == int(instances): return poll.Success() default: - return poll.Continue("running task count at %d waiting for %d (total tasks: %d)", running, instances, len(tasks)) + return poll.Continue("running task count at %d waiting for %d (total tasks: %d)", running, instances, len(result.Tasks)) } } } @@ -97,7 +97,7 @@ func JobComplete(ctx context.Context, apiClient client.ServiceAPIClient, service previousResult := "" return func(log poll.LogT) poll.Result { - tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{ + result, err := apiClient.TaskList(ctx, client.TaskListOptions{ Filters: filter, }) if err != nil { @@ -110,7 +110,7 @@ func JobComplete(ctx context.Context, apiClient client.ServiceAPIClient, service var runningSlot []int var runningID []string - for _, task := range tasks { + for _, task := range result.Tasks { // make sure the task has the same job iteration if task.JobIteration == nil || task.JobIteration.Index != jobIteration.Index { continue diff --git a/integration/service/create_test.go b/integration/service/create_test.go index 51c6adddd7..ce967bd2d2 100644 --- a/integration/service/create_test.go +++ b/integration/service/create_test.go @@ -368,19 +368,19 @@ func TestCreateServiceSysctls(t *testing.T) { // more complex) // get all tasks of the service, so we can get the container - tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{ + taskResult, err := apiClient.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("service", serviceID), }) assert.NilError(t, err) - assert.Check(t, is.Equal(len(tasks), 1)) + assert.Check(t, is.Equal(len(taskResult.Tasks), 1)) // verify that the container has the sysctl option set - ctnr, err := apiClient.ContainerInspect(ctx, tasks[0].Status.ContainerStatus.ContainerID) + ctnr, err := apiClient.ContainerInspect(ctx, taskResult.Tasks[0].Status.ContainerStatus.ContainerID) assert.NilError(t, err) assert.DeepEqual(t, ctnr.HostConfig.Sysctls, expectedSysctls) // verify that the task has the sysctl option set in the task object - assert.DeepEqual(t, tasks[0].Spec.ContainerSpec.Sysctls, expectedSysctls) + assert.DeepEqual(t, taskResult.Tasks[0].Spec.ContainerSpec.Sysctls, expectedSysctls) // verify that the service also has the sysctl set in the spec. service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID, client.ServiceInspectOptions{}) @@ -438,21 +438,21 @@ func TestCreateServiceCapabilities(t *testing.T) { // level has been tested elsewhere. // get all tasks of the service, so we can get the container - tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{ + taskResult, err := apiClient.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("service", serviceID), }) assert.NilError(t, err) - assert.Check(t, is.Equal(len(tasks), 1)) + assert.Check(t, is.Equal(len(taskResult.Tasks), 1)) // verify that the container has the capabilities option set - ctnr, err := apiClient.ContainerInspect(ctx, tasks[0].Status.ContainerStatus.ContainerID) + ctnr, err := apiClient.ContainerInspect(ctx, taskResult.Tasks[0].Status.ContainerStatus.ContainerID) assert.NilError(t, err) assert.DeepEqual(t, ctnr.HostConfig.CapAdd, capAdd) assert.DeepEqual(t, ctnr.HostConfig.CapDrop, capDrop) // verify that the task has the capabilities option set in the task object - assert.DeepEqual(t, tasks[0].Spec.ContainerSpec.CapabilityAdd, capAdd) - assert.DeepEqual(t, tasks[0].Spec.ContainerSpec.CapabilityDrop, capDrop) + assert.DeepEqual(t, taskResult.Tasks[0].Spec.ContainerSpec.CapabilityAdd, capAdd) + assert.DeepEqual(t, taskResult.Tasks[0].Spec.ContainerSpec.CapabilityDrop, capDrop) // verify that the service also has the capabilities set in the spec. service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID, client.ServiceInspectOptions{}) diff --git a/integration/service/list_test.go b/integration/service/list_test.go index 5e897f2624..d4c63bc49b 100644 --- a/integration/service/list_test.go +++ b/integration/service/list_test.go @@ -52,12 +52,12 @@ func TestServiceListWithStatuses(t *testing.T) { // serviceContainerCount function does not do. instead, we'll use a // bespoke closure right here. poll.WaitOn(t, func(log poll.LogT) poll.Result { - tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{ + taskResult, err := apiClient.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("service", id), }) running := 0 - for _, task := range tasks { + for _, task := range taskResult.Tasks { if task.Status.State == swarmtypes.TaskStateRunning { running++ } @@ -71,7 +71,7 @@ func TestServiceListWithStatuses(t *testing.T) { default: return poll.Continue( "running task count %d (%d total), waiting for %d", - running, len(tasks), i+1, + running, len(taskResult.Tasks), i+1, ) } }) diff --git a/integration/service/update_test.go b/integration/service/update_test.go index 5e5a7dda31..70d910f8ac 100644 --- a/integration/service/update_test.go +++ b/integration/service/update_test.go @@ -325,13 +325,13 @@ func TestServiceUpdatePidsLimit(t *testing.T) { func getServiceTaskContainer(ctx context.Context, t *testing.T, cli client.APIClient, serviceID string) container.InspectResponse { t.Helper() - tasks, err := cli.TaskList(ctx, client.TaskListOptions{ + taskResult, err := cli.TaskList(ctx, client.TaskListOptions{ Filters: make(client.Filters).Add("service", serviceID).Add("desired-state", "running"), }) assert.NilError(t, err) - assert.Assert(t, len(tasks) > 0) + assert.Assert(t, len(taskResult.Tasks) > 0) - ctr, err := cli.ContainerInspect(ctx, tasks[0].Status.ContainerStatus.ContainerID) + ctr, err := cli.ContainerInspect(ctx, taskResult.Tasks[0].Status.ContainerStatus.ContainerID) assert.NilError(t, err) assert.Equal(t, ctr.State.Running, true) return ctr diff --git a/internal/testutil/daemon/service.go b/internal/testutil/daemon/service.go index 4365ff4880..8a575b14f3 100644 --- a/internal/testutil/daemon/service.go +++ b/internal/testutil/daemon/service.go @@ -70,9 +70,9 @@ func (d *Daemon) GetServiceTasksWithFilters(ctx context.Context, t testing.TB, s Filters: filterArgs, } - tasks, err := cli.TaskList(ctx, options) + result, err := cli.TaskList(ctx, options) assert.NilError(t, err) - return tasks + return result.Tasks } // UpdateService updates a swarm service with the specified service constructor @@ -116,7 +116,7 @@ func (d *Daemon) GetTask(ctx context.Context, t testing.TB, id string) swarm.Tas cli := d.NewClientT(t) defer cli.Close() - task, _, err := cli.TaskInspectWithRaw(ctx, id) + result, err := cli.TaskInspect(ctx, id) assert.NilError(t, err) - return task + return result.Task } diff --git a/vendor/github.com/moby/moby/client/client_interfaces.go b/vendor/github.com/moby/moby/client/client_interfaces.go index fcb00553fc..e3359ffbda 100644 --- a/vendor/github.com/moby/moby/client/client_interfaces.go +++ b/vendor/github.com/moby/moby/client/client_interfaces.go @@ -168,8 +168,8 @@ type ServiceAPIClient interface { ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) ServiceLogs(ctx context.Context, serviceID string, options ContainerLogsOptions) (io.ReadCloser, error) TaskLogs(ctx context.Context, taskID string, options ContainerLogsOptions) (io.ReadCloser, error) - TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) - TaskList(ctx context.Context, options TaskListOptions) ([]swarm.Task, error) + TaskInspect(ctx context.Context, taskID string) (TaskInspectResult, error) + TaskList(ctx context.Context, options TaskListOptions) (TaskListResult, error) } // SwarmAPIClient defines API client methods for the swarm diff --git a/vendor/github.com/moby/moby/client/swarm_task_list_opts.go b/vendor/github.com/moby/moby/client/swarm_task_list_opts.go deleted file mode 100644 index d33f38e1e4..0000000000 --- a/vendor/github.com/moby/moby/client/swarm_task_list_opts.go +++ /dev/null @@ -1,6 +0,0 @@ -package client - -// TaskListOptions holds parameters to list tasks with. -type TaskListOptions struct { - Filters Filters -} diff --git a/vendor/github.com/moby/moby/client/task_inspect.go b/vendor/github.com/moby/moby/client/task_inspect.go index f38392d4e6..6012fe8a48 100644 --- a/vendor/github.com/moby/moby/client/task_inspect.go +++ b/vendor/github.com/moby/moby/client/task_inspect.go @@ -1,34 +1,31 @@ package client import ( - "bytes" "context" - "encoding/json" - "io" "github.com/moby/moby/api/types/swarm" ) -// TaskInspectWithRaw returns the task information and its raw representation. -func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { +// TaskInspectResult contains the result of a task inspection. +type TaskInspectResult struct { + Task swarm.Task + Raw []byte +} + +// TaskInspect returns the task information and its raw representation. +func (cli *Client) TaskInspect(ctx context.Context, taskID string) (TaskInspectResult, error) { taskID, err := trimID("task", taskID) if err != nil { - return swarm.Task{}, nil, err + return TaskInspectResult{}, err } resp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) defer ensureReaderClosed(resp) if err != nil { - return swarm.Task{}, nil, err + return TaskInspectResult{}, err } - body, err := io.ReadAll(resp.Body) - if err != nil { - return swarm.Task{}, nil, err - } - - var response swarm.Task - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&response) - return response, body, err + var out TaskInspectResult + out.Raw, err = decodeWithRaw(resp, &out.Task) + return out, err } diff --git a/vendor/github.com/moby/moby/client/task_list.go b/vendor/github.com/moby/moby/client/task_list.go index bea82ad1bf..0511c1c735 100644 --- a/vendor/github.com/moby/moby/client/task_list.go +++ b/vendor/github.com/moby/moby/client/task_list.go @@ -8,8 +8,18 @@ import ( "github.com/moby/moby/api/types/swarm" ) +// TaskListOptions holds parameters to list tasks with. +type TaskListOptions struct { + Filters Filters +} + +// TaskListResult contains the result of a task list operation. +type TaskListResult struct { + Tasks []swarm.Task +} + // TaskList returns the list of tasks. -func (cli *Client) TaskList(ctx context.Context, options TaskListOptions) ([]swarm.Task, error) { +func (cli *Client) TaskList(ctx context.Context, options TaskListOptions) (TaskListResult, error) { query := url.Values{} options.Filters.updateURLValues(query) @@ -17,10 +27,10 @@ func (cli *Client) TaskList(ctx context.Context, options TaskListOptions) ([]swa resp, err := cli.get(ctx, "/tasks", query, nil) defer ensureReaderClosed(resp) if err != nil { - return nil, err + return TaskListResult{}, err } var tasks []swarm.Task err = json.NewDecoder(resp.Body).Decode(&tasks) - return tasks, err + return TaskListResult{Tasks: tasks}, err }