diff --git a/client/client_interfaces.go b/client/client_interfaces.go index 4ab5adb409..6ef1964d71 100644 --- a/client/client_interfaces.go +++ b/client/client_interfaces.go @@ -73,7 +73,7 @@ type ContainerAPIClient interface { ContainerStop(ctx context.Context, container string, options ContainerStopOptions) (ContainerStopResult, 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) + ContainerUpdate(ctx context.Context, container string, updateConfig ContainerUpdateOptions) (ContainerUpdateResult, error) ContainerWait(ctx context.Context, container string, options ContainerWaitOptions) ContainerWaitResult CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, container.PathStat, error) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options CopyToContainerOptions) error diff --git a/client/container_update.go b/client/container_update.go index fc524b1c91..a1d4d249a9 100644 --- a/client/container_update.go +++ b/client/container_update.go @@ -7,20 +7,40 @@ import ( "github.com/moby/moby/api/types/container" ) +// ContainerUpdateOptions holds options for [Client.ContainerUpdate]. +type ContainerUpdateOptions struct { + Resources *container.Resources + RestartPolicy *container.RestartPolicy +} + +// ContainerUpdateResult is the result from updating a container. +type ContainerUpdateResult struct { + // Warnings encountered when updating the container. + Warnings []string +} + // ContainerUpdate updates the resources of a container. -func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) { +func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, options ContainerUpdateOptions) (ContainerUpdateResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.UpdateResponse{}, err + return ContainerUpdateResult{}, err + } + + updateConfig := container.UpdateConfig{} + if options.Resources != nil { + updateConfig.Resources = *options.Resources + } + if options.RestartPolicy != nil { + updateConfig.RestartPolicy = *options.RestartPolicy } resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) defer ensureReaderClosed(resp) if err != nil { - return container.UpdateResponse{}, err + return ContainerUpdateResult{}, err } var response container.UpdateResponse err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerUpdateResult{Warnings: response.Warnings}, err } diff --git a/client/container_update_test.go b/client/container_update_test.go index f2987f094c..d4f83e126f 100644 --- a/client/container_update_test.go +++ b/client/container_update_test.go @@ -14,14 +14,14 @@ import ( func TestContainerUpdateError(t *testing.T) { client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error"))) assert.NilError(t, err) - _, err = client.ContainerUpdate(context.Background(), "nothing", container.UpdateConfig{}) + _, err = client.ContainerUpdate(context.Background(), "nothing", ContainerUpdateOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal)) - _, err = client.ContainerUpdate(context.Background(), "", container.UpdateConfig{}) + _, err = client.ContainerUpdate(context.Background(), "", ContainerUpdateOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) - _, err = client.ContainerUpdate(context.Background(), " ", container.UpdateConfig{}) + _, err = client.ContainerUpdate(context.Background(), " ", ContainerUpdateOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) } @@ -37,11 +37,11 @@ func TestContainerUpdate(t *testing.T) { })) assert.NilError(t, err) - _, err = client.ContainerUpdate(context.Background(), "container_id", container.UpdateConfig{ - Resources: container.Resources{ + _, err = client.ContainerUpdate(context.Background(), "container_id", ContainerUpdateOptions{ + Resources: &container.Resources{ CPUPeriod: 1, }, - RestartPolicy: container.RestartPolicy{ + RestartPolicy: &container.RestartPolicy{ Name: "always", }, }) diff --git a/integration/container/update_linux_test.go b/integration/container/update_linux_test.go index 8542f24bad..60bb206574 100644 --- a/integration/container/update_linux_test.go +++ b/integration/container/update_linux_test.go @@ -37,8 +37,8 @@ func TestUpdateMemory(t *testing.T) { setMemorySwap int64 = 524288000 ) - _, err := apiClient.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{ - Resources: containertypes.Resources{ + _, err := apiClient.ContainerUpdate(ctx, cID, client.ContainerUpdateOptions{ + Resources: &containertypes.Resources{ Memory: setMemory, MemorySwap: setMemorySwap, }, @@ -100,16 +100,16 @@ func TestUpdateCPUQuota(t *testing.T) { // On v2, specifying CPUQuota without CPUPeriod is currently broken: // https://github.com/opencontainers/runc/issues/2456 // As a workaround we set them together. - _, err := apiClient.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{ - Resources: containertypes.Resources{ + _, err := apiClient.ContainerUpdate(ctx, cID, client.ContainerUpdateOptions{ + Resources: &containertypes.Resources{ CPUQuota: test.update, CPUPeriod: 100000, }, }) assert.NilError(t, err) } else { - _, err := apiClient.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{ - Resources: containertypes.Resources{ + _, err := apiClient.ContainerUpdate(ctx, cID, client.ContainerUpdateOptions{ + Resources: &containertypes.Resources{ CPUQuota: test.update, }, }) @@ -185,8 +185,8 @@ func TestUpdatePidsLimit(t *testing.T) { // Using "network=host" to speed up creation (13.96s vs 6.54s) cID := container.Run(ctx, t, apiClient, container.WithPidsLimit(test.initial), container.WithNetworkMode("host")) - _, err := c.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{ - Resources: containertypes.Resources{ + _, err := c.ContainerUpdate(ctx, cID, client.ContainerUpdateOptions{ + Resources: &containertypes.Resources{ PidsLimit: test.update, }, }) diff --git a/integration/container/update_test.go b/integration/container/update_test.go index ee58d57c36..6226e06400 100644 --- a/integration/container/update_test.go +++ b/integration/container/update_test.go @@ -24,8 +24,8 @@ func TestUpdateRestartPolicy(t *testing.T) { } }) - _, err := apiClient.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{ - RestartPolicy: containertypes.RestartPolicy{ + _, err := apiClient.ContainerUpdate(ctx, cID, client.ContainerUpdateOptions{ + RestartPolicy: &containertypes.RestartPolicy{ Name: "on-failure", MaximumRetryCount: 5, }, @@ -51,8 +51,8 @@ func TestUpdateRestartWithAutoRemove(t *testing.T) { cID := container.Run(ctx, t, apiClient, container.WithAutoRemove) - _, err := apiClient.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{ - RestartPolicy: containertypes.RestartPolicy{ + _, err := apiClient.ContainerUpdate(ctx, cID, client.ContainerUpdateOptions{ + RestartPolicy: &containertypes.RestartPolicy{ Name: "always", }, }) diff --git a/vendor/github.com/moby/moby/client/client_interfaces.go b/vendor/github.com/moby/moby/client/client_interfaces.go index 4ab5adb409..6ef1964d71 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 { ContainerStop(ctx context.Context, container string, options ContainerStopOptions) (ContainerStopResult, 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) + ContainerUpdate(ctx context.Context, container string, updateConfig ContainerUpdateOptions) (ContainerUpdateResult, error) ContainerWait(ctx context.Context, container string, options ContainerWaitOptions) ContainerWaitResult CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, container.PathStat, error) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options CopyToContainerOptions) error diff --git a/vendor/github.com/moby/moby/client/container_update.go b/vendor/github.com/moby/moby/client/container_update.go index fc524b1c91..a1d4d249a9 100644 --- a/vendor/github.com/moby/moby/client/container_update.go +++ b/vendor/github.com/moby/moby/client/container_update.go @@ -7,20 +7,40 @@ import ( "github.com/moby/moby/api/types/container" ) +// ContainerUpdateOptions holds options for [Client.ContainerUpdate]. +type ContainerUpdateOptions struct { + Resources *container.Resources + RestartPolicy *container.RestartPolicy +} + +// ContainerUpdateResult is the result from updating a container. +type ContainerUpdateResult struct { + // Warnings encountered when updating the container. + Warnings []string +} + // ContainerUpdate updates the resources of a container. -func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) { +func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, options ContainerUpdateOptions) (ContainerUpdateResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.UpdateResponse{}, err + return ContainerUpdateResult{}, err + } + + updateConfig := container.UpdateConfig{} + if options.Resources != nil { + updateConfig.Resources = *options.Resources + } + if options.RestartPolicy != nil { + updateConfig.RestartPolicy = *options.RestartPolicy } resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) defer ensureReaderClosed(resp) if err != nil { - return container.UpdateResponse{}, err + return ContainerUpdateResult{}, err } var response container.UpdateResponse err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerUpdateResult{Warnings: response.Warnings}, err }