From 056e314645801598f80898029c5d7cbf9f751ec8 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 24 Oct 2025 22:08:17 +0200 Subject: [PATCH 1/2] vendor: github.com/moby/moby/api, moby/moby/client master Signed-off-by: Sebastiaan van Stijn --- cli/command/completion/functions.go | 2 +- cli/command/completion/functions_test.go | 6 +- cli/command/container/attach.go | 10 +- cli/command/container/client_test.go | 45 ++-- cli/command/container/commit_test.go | 17 +- cli/command/container/create.go | 18 +- cli/command/container/create_test.go | 45 +--- cli/command/container/diff.go | 5 +- cli/command/container/diff_test.go | 39 ++- cli/command/container/exec_test.go | 16 +- cli/command/container/formatter_diff.go | 5 +- cli/command/container/formatter_diff_test.go | 11 +- cli/command/container/run.go | 4 +- cli/command/container/run_test.go | 51 ++-- cli/command/container/start.go | 7 +- cli/command/formatter/volume.go | 4 +- cli/command/formatter/volume_test.go | 6 +- cli/command/image/import_test.go | 1 - cli/command/image/load_test.go | 2 +- cli/command/image/remove.go | 2 +- cli/command/image/remove_test.go | 8 +- cli/command/node/demote_test.go | 8 +- cli/command/node/promote_test.go | 8 +- cli/command/node/update.go | 2 +- cli/command/node/update_test.go | 20 +- cli/command/plugin/client_test.go | 3 +- cli/command/service/client_test.go | 6 +- cli/command/service/create.go | 14 +- cli/command/service/rollback.go | 4 +- cli/command/service/rollback_test.go | 9 +- cli/command/service/scale.go | 5 +- cli/command/service/update.go | 86 ++++--- cli/command/stack/client_test.go | 6 +- cli/command/stack/deploy_composefile.go | 11 +- cli/command/stack/deploy_test.go | 13 +- cli/command/swarm/ca.go | 5 +- cli/command/swarm/ca_test.go | 2 +- cli/command/swarm/client_test.go | 3 +- cli/command/swarm/join_token.go | 5 +- cli/command/swarm/unlock_key.go | 6 +- cli/command/swarm/update.go | 5 +- cli/command/swarm/update_test.go | 16 +- cli/command/system/completion.go | 4 +- cli/command/system/completion_test.go | 8 +- cli/command/volume/inspect_test.go | 6 +- cli/command/volume/list.go | 12 +- cli/command/volume/list_test.go | 232 +++++++++--------- cli/compose/loader/loader.go | 2 +- cmd/docker/docker.go | 2 +- e2e/container/run_test.go | 2 +- internal/test/builders/volume.go | 6 +- vendor.mod | 4 +- vendor.sum | 8 +- .../moby/moby/api/types/swarm/task.go | 11 + .../moby/moby/client/build_prune.go | 2 +- vendor/github.com/moby/moby/client/client.go | 2 +- .../moby/moby/client/client_interfaces.go | 15 +- .../moby/moby/client/config_inspect.go | 4 +- .../moby/moby/client/container_attach.go | 16 +- .../moby/moby/client/container_commit.go | 17 +- .../moby/moby/client/container_create.go | 46 ++-- .../moby/moby/client/container_create_opts.go | 25 ++ .../moby/moby/client/container_diff.go | 10 +- .../moby/moby/client/container_diff_opts.go | 13 + .../moby/moby/client/container_exec.go | 35 ++- vendor/github.com/moby/moby/client/errors.go | 2 +- .../moby/moby/client/image_import.go | 2 +- .../moby/moby/client/image_import_opts.go | 11 +- .../github.com/moby/moby/client/image_list.go | 2 +- .../moby/moby/client/image_remove.go | 2 +- .../moby/moby/client/image_remove_opts.go | 2 +- .../moby/moby/client/network_inspect.go | 4 +- .../moby/moby/client/node_inspect.go | 5 +- .../github.com/moby/moby/client/node_list.go | 5 + .../moby/moby/client/node_remove.go | 4 + .../moby/moby/client/node_update.go | 10 +- .../types => client/pkg}/versions/compare.go | 0 .../moby/moby/client/plugin_inspect.go | 4 +- .../moby/moby/client/secret_inspect.go | 4 +- .../moby/moby/client/service_create.go | 28 ++- .../moby/moby/client/service_inspect.go | 4 +- .../moby/moby/client/service_update.go | 27 +- .../moby/client/swarm_node_inspect_opts.go | 4 - .../moby/moby/client/swarm_node_list_opts.go | 6 - .../moby/client/swarm_node_remove_opts.go | 6 - .../moby/client/swarm_node_update_opts.go | 9 - .../moby/moby/client/swarm_update.go | 9 +- .../moby/moby/client/task_inspect.go | 4 +- vendor/github.com/moby/moby/client/utils.go | 4 +- .../moby/moby/client/volume_inspect.go | 4 +- .../moby/moby/client/volume_list.go | 28 ++- vendor/modules.txt | 6 +- 92 files changed, 639 insertions(+), 580 deletions(-) create mode 100644 vendor/github.com/moby/moby/client/container_create_opts.go create mode 100644 vendor/github.com/moby/moby/client/container_diff_opts.go rename vendor/github.com/moby/moby/{api/types => client/pkg}/versions/compare.go (100%) delete mode 100644 vendor/github.com/moby/moby/client/swarm_node_inspect_opts.go delete mode 100644 vendor/github.com/moby/moby/client/swarm_node_list_opts.go delete mode 100644 vendor/github.com/moby/moby/client/swarm_node_remove_opts.go delete mode 100644 vendor/github.com/moby/moby/client/swarm_node_update_opts.go diff --git a/cli/command/completion/functions.go b/cli/command/completion/functions.go index a85b9f1f8f..d8a5a71d32 100644 --- a/cli/command/completion/functions.go +++ b/cli/command/completion/functions.go @@ -115,7 +115,7 @@ func VolumeNames(dockerCLI APIClientProvider) cobra.CompletionFunc { return nil, cobra.ShellCompDirectiveError } var names []string - for _, vol := range res.Items.Volumes { + for _, vol := range res.Items { names = append(names, vol.Name) } return names, cobra.ShellCompDirectiveNoFileComp diff --git a/cli/command/completion/functions_test.go b/cli/command/completion/functions_test.go index ed426be60e..67803f9a0d 100644 --- a/cli/command/completion/functions_test.go +++ b/cli/command/completion/functions_test.go @@ -310,7 +310,7 @@ func TestCompletePlatforms(t *testing.T) { func TestCompleteVolumeNames(t *testing.T) { tests := []struct { doc string - volumes []*volume.Volume + volumes []volume.Volume expOut []string expDirective cobra.ShellCompDirective }{ @@ -320,7 +320,7 @@ func TestCompleteVolumeNames(t *testing.T) { }, { doc: "with results", - volumes: []*volume.Volume{ + volumes: []volume.Volume{ {Name: "volume-c"}, {Name: "volume-b"}, {Name: "volume-a"}, @@ -341,7 +341,7 @@ func TestCompleteVolumeNames(t *testing.T) { if tc.expDirective == cobra.ShellCompDirectiveError { return client.VolumeListResult{}, errors.New("some error occurred") } - return client.VolumeListResult{Items: volume.ListResponse{Volumes: tc.volumes}}, nil + return client.VolumeListResult{Items: tc.volumes}, nil }, }}) diff --git a/cli/command/container/attach.go b/cli/command/container/attach.go index 57dcf446b8..8386219ff5 100644 --- a/cli/command/container/attach.go +++ b/cli/command/container/attach.go @@ -114,11 +114,11 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o defer signal.StopCatch(sigc) } - resp, errAttach := apiClient.ContainerAttach(ctx, containerID, options) - if errAttach != nil { - return errAttach + res, err := apiClient.ContainerAttach(ctx, containerID, options) + if err != nil { + return err } - defer resp.Close() + defer res.HijackedResponse.Close() // If use docker attach command to attach to a stop container, it will return // "You cannot attach to a stopped container" error, it's ok, but when @@ -142,7 +142,7 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o inputStream: in, outputStream: dockerCLI.Out(), errorStream: dockerCLI.Err(), - resp: resp, + resp: res.HijackedResponse, tty: c.Config.Tty, detachKeys: options.DetachKeys, } diff --git a/cli/command/container/client_test.go b/cli/command/container/client_test.go index 4911148f5c..8825ddce4d 100644 --- a/cli/command/container/client_test.go +++ b/cli/command/container/client_test.go @@ -5,22 +5,16 @@ import ( "io" "github.com/moby/moby/api/types/container" - "github.com/moby/moby/api/types/network" "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) type fakeClient struct { client.Client - inspectFunc func(string) (container.InspectResponse, error) - execInspectFunc func(execID string) (client.ExecInspectResult, error) - execCreateFunc func(containerID string, options client.ExecCreateOptions) (client.ExecCreateResult, error) - createContainerFunc func(config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, - containerName string) (container.CreateResponse, error) + inspectFunc func(string) (container.InspectResponse, error) + execInspectFunc func(execID string) (client.ExecInspectResult, error) + execCreateFunc func(containerID string, options client.ExecCreateOptions) (client.ExecCreateResult, error) + createContainerFunc func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) containerStartFunc func(containerID string, options client.ContainerStartOptions) error imageCreateFunc func(ctx context.Context, parentReference string, options client.ImageCreateOptions) (client.ImageCreateResult, error) infoFunc func() (system.Info, error) @@ -36,10 +30,10 @@ type fakeClient struct { containerStopFunc func(ctx context.Context, containerID string, options client.ContainerStopOptions) error containerKillFunc func(ctx context.Context, containerID, signal string) error containerPruneFunc func(ctx context.Context, options client.ContainerPruneOptions) (client.ContainerPruneResult, error) - containerAttachFunc func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) - containerDiffFunc func(ctx context.Context, containerID string) ([]container.FilesystemChange, error) + containerAttachFunc func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) + containerDiffFunc func(ctx context.Context, containerID string) (client.ContainerDiffResult, error) containerRenameFunc func(ctx context.Context, oldName, newName string) error - containerCommitFunc func(ctx context.Context, container string, options client.ContainerCommitOptions) (container.CommitResponse, error) + containerCommitFunc func(ctx context.Context, container string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) containerPauseFunc func(ctx context.Context, container string) error Version string } @@ -76,18 +70,11 @@ func (*fakeClient) ExecStart(context.Context, string, client.ExecStartOptions) ( return client.ExecStartResult{}, nil } -func (f *fakeClient) ContainerCreate( - _ context.Context, - config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, - containerName string, -) (container.CreateResponse, error) { +func (f *fakeClient) ContainerCreate(_ context.Context, options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { if f.createContainerFunc != nil { - return f.createContainerFunc(config, hostConfig, networkingConfig, platform, containerName) + return f.createContainerFunc(options) } - return container.CreateResponse{}, nil + return client.ContainerCreateResult{}, nil } func (f *fakeClient) ContainerRemove(ctx context.Context, containerID string, options client.ContainerRemoveOptions) error { @@ -192,19 +179,19 @@ func (f *fakeClient) ContainerStop(ctx context.Context, containerID string, opti return nil } -func (f *fakeClient) ContainerAttach(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) { +func (f *fakeClient) ContainerAttach(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) { if f.containerAttachFunc != nil { return f.containerAttachFunc(ctx, containerID, options) } - return client.HijackedResponse{}, nil + return client.ContainerAttachResult{}, nil } -func (f *fakeClient) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) { +func (f *fakeClient) ContainerDiff(ctx context.Context, containerID string, _ client.ContainerDiffOptions) (client.ContainerDiffResult, error) { if f.containerDiffFunc != nil { return f.containerDiffFunc(ctx, containerID) } - return []container.FilesystemChange{}, nil + return client.ContainerDiffResult{}, nil } func (f *fakeClient) ContainerRename(ctx context.Context, oldName, newName string) error { @@ -215,11 +202,11 @@ func (f *fakeClient) ContainerRename(ctx context.Context, oldName, newName strin return nil } -func (f *fakeClient) ContainerCommit(ctx context.Context, containerID string, options client.ContainerCommitOptions) (container.CommitResponse, error) { +func (f *fakeClient) ContainerCommit(ctx context.Context, containerID string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) { if f.containerCommitFunc != nil { return f.containerCommitFunc(ctx, containerID, options) } - return container.CommitResponse{}, nil + return client.ContainerCommitResult{}, nil } func (f *fakeClient) ContainerPause(ctx context.Context, containerID string) error { diff --git a/cli/command/container/commit_test.go b/cli/command/container/commit_test.go index c01d49b725..fa8164d029 100644 --- a/cli/command/container/commit_test.go +++ b/cli/command/container/commit_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/docker/cli/internal/test" - "github.com/moby/moby/api/types/container" "github.com/moby/moby/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -15,18 +14,14 @@ import ( func TestRunCommit(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerCommitFunc: func( - ctx context.Context, - ctr string, - options client.ContainerCommitOptions, - ) (container.CommitResponse, error) { + containerCommitFunc: func(ctx context.Context, ctr string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) { assert.Check(t, is.Equal(options.Author, "Author Name ")) assert.Check(t, is.DeepEqual(options.Changes, []string{"EXPOSE 80"})) assert.Check(t, is.Equal(options.Comment, "commit message")) assert.Check(t, is.Equal(options.NoPause, true)) assert.Check(t, is.Equal(ctr, "container-id")) - return container.CommitResponse{ID: "image-id"}, nil + return client.ContainerCommitResult{ID: "image-id"}, nil }, }) @@ -52,12 +47,8 @@ func TestRunCommitClientError(t *testing.T) { clientError := errors.New("client error") cli := test.NewFakeCli(&fakeClient{ - containerCommitFunc: func( - ctx context.Context, - ctr string, - options client.ContainerCommitOptions, - ) (container.CommitResponse, error) { - return container.CommitResponse{}, clientError + containerCommitFunc: func(ctx context.Context, ctr string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) { + return client.ContainerCommitResult{}, clientError }, }) diff --git a/cli/command/container/create.go b/cli/command/container/create.go index a8969e4f11..a645b49989 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -332,7 +332,14 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = dockerCli.Out().GetTtySize() - response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, platform, options.name) + response, err := dockerCli.Client().ContainerCreate(ctx, client.ContainerCreateOptions{ + Name: options.name, + // Image: config.Image, // TODO(thaJeztah): pass image-ref separate + Platform: platform, + Config: config, + HostConfig: hostConfig, + NetworkingConfig: networkingConfig, + }) if err != nil { // Pull image if it does not exist locally and we have the PullImageMissing option. Default behavior. if errdefs.IsNotFound(err) && namedRef != nil && options.pull == PullImageMissing { @@ -346,7 +353,14 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c } var retryErr error - response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, platform, options.name) + response, retryErr = dockerCli.Client().ContainerCreate(ctx, client.ContainerCreateOptions{ + Name: options.name, + // Image: config.Image, // TODO(thaJeztah): pass image-ref separate + Platform: platform, + Config: config, + HostConfig: hostConfig, + NetworkingConfig: networkingConfig, + }) if retryErr != nil { return "", retryErr } diff --git a/cli/command/container/create_test.go b/cli/command/container/create_test.go index 3f13477b19..234b6bca4f 100644 --- a/cli/command/container/create_test.go +++ b/cli/command/container/create_test.go @@ -16,10 +16,8 @@ import ( "github.com/docker/cli/internal/test/notary" "github.com/google/go-cmp/cmp" "github.com/moby/moby/api/types/container" - "github.com/moby/moby/api/types/network" "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/pflag" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -117,19 +115,13 @@ func TestCreateContainerImagePullPolicy(t *testing.T) { pullCounter := 0 apiClient := &fakeClient{ - createContainerFunc: func( - config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, - containerName string, - ) (container.CreateResponse, error) { + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { defer func() { tc.ResponseCounter++ }() switch tc.ResponseCounter { case 0: - return container.CreateResponse{}, fakeNotFound{} + return client.ContainerCreateResult{}, fakeNotFound{} default: - return container.CreateResponse{ID: containerID}, nil + return client.ContainerCreateResult{ID: containerID}, nil } }, imageCreateFunc: func(ctx context.Context, parentReference string, options client.ImageCreateOptions) (client.ImageCreateResult, error) { @@ -251,13 +243,8 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Setenv("DOCKER_CONTENT_TRUST", "true") fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, - containerName string, - ) (container.CreateResponse, error) { - return container.CreateResponse{}, errors.New("shouldn't try to pull image") + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + return client.ContainerCreateResult{}, errors.New("shouldn't try to pull image") }, }) fakeCLI.SetNotaryClient(tc.notaryFunc) @@ -296,13 +283,8 @@ func TestNewCreateCommandWithWarnings(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, - containerName string, - ) (container.CreateResponse, error) { - return container.CreateResponse{Warnings: tc.warnings}, nil + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + return client.ContainerCreateResult{Warnings: tc.warnings}, nil }, }) cmd := newCreateCommand(fakeCLI) @@ -335,15 +317,10 @@ func TestCreateContainerWithProxyConfig(t *testing.T) { sort.Strings(expected) fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, - containerName string, - ) (container.CreateResponse, error) { - sort.Strings(config.Env) - assert.DeepEqual(t, config.Env, expected) - return container.CreateResponse{}, nil + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + sort.Strings(options.Config.Env) + assert.DeepEqual(t, options.Config.Env, expected) + return client.ContainerCreateResult{}, nil }, }) fakeCLI.SetConfigFile(&configfile.ConfigFile{ diff --git a/cli/command/container/diff.go b/cli/command/container/diff.go index 164ebf02a0..feb0f843e8 100644 --- a/cli/command/container/diff.go +++ b/cli/command/container/diff.go @@ -7,6 +7,7 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/completion" "github.com/docker/cli/cli/command/formatter" + "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -28,7 +29,7 @@ func newDiffCommand(dockerCLI command.Cli) *cobra.Command { } func runDiff(ctx context.Context, dockerCLI command.Cli, containerID string) error { - changes, err := dockerCLI.Client().ContainerDiff(ctx, containerID) + res, err := dockerCLI.Client().ContainerDiff(ctx, containerID, client.ContainerDiffOptions{}) if err != nil { return err } @@ -36,5 +37,5 @@ func runDiff(ctx context.Context, dockerCLI command.Cli, containerID string) err Output: dockerCLI.Out(), Format: newDiffFormat("{{.Type}} {{.Path}}"), } - return diffFormatWrite(diffCtx, changes) + return diffFormatWrite(diffCtx, res) } diff --git a/cli/command/container/diff_test.go b/cli/command/container/diff_test.go index d2504858b7..1e941d9745 100644 --- a/cli/command/container/diff_test.go +++ b/cli/command/container/diff_test.go @@ -9,28 +9,28 @@ import ( "github.com/docker/cli/internal/test" "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) func TestRunDiff(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerDiffFunc: func( - ctx context.Context, - containerID string, - ) ([]container.FilesystemChange, error) { - return []container.FilesystemChange{ - { - Kind: container.ChangeModify, - Path: "/path/to/file0", - }, - { - Kind: container.ChangeAdd, - Path: "/path/to/file1", - }, - { - Kind: container.ChangeDelete, - Path: "/path/to/file2", + containerDiffFunc: func(ctx context.Context, containerID string) (client.ContainerDiffResult, error) { + return client.ContainerDiffResult{ + Changes: []container.FilesystemChange{ + { + Kind: container.ChangeModify, + Path: "/path/to/file0", + }, + { + Kind: container.ChangeAdd, + Path: "/path/to/file1", + }, + { + Kind: container.ChangeDelete, + Path: "/path/to/file2", + }, }, }, nil }, @@ -60,11 +60,8 @@ func TestRunDiffClientError(t *testing.T) { clientError := errors.New("client error") cli := test.NewFakeCli(&fakeClient{ - containerDiffFunc: func( - ctx context.Context, - containerID string, - ) ([]container.FilesystemChange, error) { - return nil, clientError + containerDiffFunc: func(ctx context.Context, containerID string) (client.ContainerDiffResult, error) { + return client.ContainerDiffResult{}, clientError }, }) diff --git a/cli/command/container/exec_test.go b/cli/command/container/exec_test.go index f344a218e9..5a86c22624 100644 --- a/cli/command/container/exec_test.go +++ b/cli/command/container/exec_test.go @@ -119,7 +119,7 @@ TWO=2 }, options: func() ExecOptions { o := withDefaultOpts(ExecOptions{}) - o.EnvFile.Set(tmpFile.Path()) + _ = o.EnvFile.Set(tmpFile.Path()) return o }(), }, @@ -132,8 +132,8 @@ TWO=2 }, options: func() ExecOptions { o := withDefaultOpts(ExecOptions{}) - o.EnvFile.Set(tmpFile.Path()) - o.Env.Set("ONE=override") + _ = o.EnvFile.Set(tmpFile.Path()) + _ = o.Env.Set("ONE=override") return o }(), }, @@ -150,7 +150,7 @@ TWO=2 func TestParseExecNoSuchFile(t *testing.T) { execOpts := withDefaultOpts(ExecOptions{}) - execOpts.EnvFile.Set("no-such-env-file") + assert.Check(t, execOpts.EnvFile.Set("no-such-env-file")) execConfig, err := parseExec(execOpts, &configfile.ConfigFile{}) assert.ErrorContains(t, err, "no-such-env-file") assert.Check(t, os.IsNotExist(err)) @@ -195,7 +195,7 @@ func TestRunExec(t *testing.T) { t.Run(testcase.doc, func(t *testing.T) { fakeCLI := test.NewFakeCli(testcase.client) - err := RunExec(context.TODO(), fakeCLI, "thecontainer", testcase.options) + err := RunExec(context.TODO(), fakeCLI, "the-container", testcase.options) if testcase.expectedError != "" { assert.ErrorContains(t, err, testcase.expectedError) } else if !assert.Check(t, err) { @@ -208,7 +208,7 @@ func TestRunExec(t *testing.T) { } func execCreateWithID(_ string, _ client.ExecCreateOptions) (client.ExecCreateResult, error) { - return client.ExecCreateResult{ExecCreateResponse: container.ExecCreateResponse{ID: "execid"}}, nil + return client.ExecCreateResult{ID: "exec-id"}, nil } func TestGetExecExitStatus(t *testing.T) { @@ -238,9 +238,7 @@ func TestGetExecExitStatus(t *testing.T) { apiClient := &fakeClient{ execInspectFunc: func(id string) (client.ExecInspectResult, error) { assert.Check(t, is.Equal(execID, id)) - return client.ExecInspectResult{ - ExecInspect: client.ExecInspect{ExitCode: testcase.exitCode}, - }, testcase.inspectError + return client.ExecInspectResult{ExitCode: testcase.exitCode}, testcase.inspectError }, } err := getExecExitStatus(context.Background(), apiClient, execID) diff --git a/cli/command/container/formatter_diff.go b/cli/command/container/formatter_diff.go index a62552b6ff..35c48d5d1b 100644 --- a/cli/command/container/formatter_diff.go +++ b/cli/command/container/formatter_diff.go @@ -3,6 +3,7 @@ package container import ( "github.com/docker/cli/cli/command/formatter" "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" ) const ( @@ -21,9 +22,9 @@ func newDiffFormat(source string) formatter.Format { } // diffFormatWrite writes formatted diff using the [formatter.Context]. -func diffFormatWrite(fmtCtx formatter.Context, changes []container.FilesystemChange) error { +func diffFormatWrite(fmtCtx formatter.Context, changes client.ContainerDiffResult) error { return fmtCtx.Write(newDiffContext(), func(format func(subContext formatter.SubContext) error) error { - for _, change := range changes { + for _, change := range changes.Changes { if err := format(&diffContext{c: change}); err != nil { return err } diff --git a/cli/command/container/formatter_diff_test.go b/cli/command/container/formatter_diff_test.go index c6d10de943..0d2849d25c 100644 --- a/cli/command/container/formatter_diff_test.go +++ b/cli/command/container/formatter_diff_test.go @@ -6,6 +6,7 @@ import ( "github.com/docker/cli/cli/command/formatter" "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "gotest.tools/v3/assert" ) @@ -40,10 +41,12 @@ D: /usr/app/old_app.js }, } - diffs := []container.FilesystemChange{ - {Kind: container.ChangeModify, Path: "/var/log/app.log"}, - {Kind: container.ChangeAdd, Path: "/usr/app/app.js"}, - {Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"}, + diffs := client.ContainerDiffResult{ + Changes: []container.FilesystemChange{ + {Kind: container.ChangeModify, Path: "/var/log/app.log"}, + {Kind: container.ChangeAdd, Path: "/usr/app/app.js"}, + {Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"}, + }, } for _, tc := range cases { diff --git a/cli/command/container/run.go b/cli/command/container/run.go index f2c634fd01..64836b0a97 100644 --- a/cli/command/container/run.go +++ b/cli/command/container/run.go @@ -290,7 +290,7 @@ func attachContainer(ctx context.Context, dockerCli command.Cli, containerID str inputStream: in, outputStream: out, errorStream: cerr, - resp: resp, + resp: resp.HijackedResponse, tty: config.Tty, detachKeys: options.DetachKeys, } @@ -301,7 +301,7 @@ func attachContainer(ctx context.Context, dockerCli command.Cli, containerID str return errAttach }() }() - return resp.Close, nil + return resp.HijackedResponse.Close, nil } // withHelp decorates the error with a suggestion to use "--help". diff --git a/cli/command/container/run_test.go b/cli/command/container/run_test.go index c853766a47..94f31d2c8e 100644 --- a/cli/command/container/run_test.go +++ b/cli/command/container/run_test.go @@ -18,9 +18,7 @@ import ( "github.com/moby/moby/api/pkg/streamformatter" "github.com/moby/moby/api/types" "github.com/moby/moby/api/types/container" - "github.com/moby/moby/api/types/network" "github.com/moby/moby/client" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/pflag" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -56,10 +54,8 @@ func TestRunValidateFlags(t *testing.T) { func TestRunLabel(t *testing.T) { fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *ocispec.Platform, _ string) (container.CreateResponse, error) { - return container.CreateResponse{ - ID: "id", - }, nil + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + return client.ContainerCreateResult{ID: "id"}, nil }, Version: client.MaxAPIVersion, }) @@ -79,19 +75,19 @@ func TestRunAttach(t *testing.T) { var conn net.Conn attachCh := make(chan struct{}) fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *ocispec.Platform, _ string) (container.CreateResponse, error) { - return container.CreateResponse{ - ID: "id", - }, nil + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + return client.ContainerCreateResult{ID: "id"}, nil }, - containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) { + containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) { server, clientConn := net.Pipe() conn = server t.Cleanup(func() { _ = server.Close() }) attachCh <- struct{}{} - return client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), nil + return client.ContainerAttachResult{ + HijackedResponse: client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), + }, nil }, waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) { responseChan := make(chan container.WaitResponse, 1) @@ -150,10 +146,8 @@ func TestRunAttachTermination(t *testing.T) { killCh := make(chan struct{}) attachCh := make(chan struct{}) fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *ocispec.Platform, _ string) (container.CreateResponse, error) { - return container.CreateResponse{ - ID: "id", - }, nil + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + return client.ContainerCreateResult{ID: "id"}, nil }, containerKillFunc: func(ctx context.Context, containerID, sig string) error { if sig == "TERM" { @@ -161,14 +155,16 @@ func TestRunAttachTermination(t *testing.T) { } return nil }, - containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) { + containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) { server, clientConn := net.Pipe() conn = server t.Cleanup(func() { _ = server.Close() }) attachCh <- struct{}{} - return client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), nil + return client.ContainerAttachResult{ + HijackedResponse: client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), + }, nil }, waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) { responseChan := make(chan container.WaitResponse, 1) @@ -227,13 +223,11 @@ func TestRunPullTermination(t *testing.T) { attachCh := make(chan struct{}) fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, containerName string, - ) (container.CreateResponse, error) { - return container.CreateResponse{}, errors.New("shouldn't try to create a container") + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + return client.ContainerCreateResult{}, errors.New("shouldn't try to create a container") }, - containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) { - return client.HijackedResponse{}, errors.New("shouldn't try to attach to a container") + containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) { + return client.ContainerAttachResult{}, errors.New("shouldn't try to attach to a container") }, imageCreateFunc: func(ctx context.Context, parentReference string, options client.ImageCreateOptions) (client.ImageCreateResult, error) { server, respReader := net.Pipe() @@ -325,13 +319,8 @@ func TestRunCommandWithContentTrustErrors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Setenv("DOCKER_CONTENT_TRUST", "true") fakeCLI := test.NewFakeCli(&fakeClient{ - createContainerFunc: func(config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - platform *ocispec.Platform, - containerName string, - ) (container.CreateResponse, error) { - return container.CreateResponse{}, errors.New("shouldn't try to pull image") + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + return client.ContainerCreateResult{}, errors.New("shouldn't try to pull image") }, }) fakeCLI.SetNotaryClient(tc.notaryFunc) diff --git a/cli/command/container/start.go b/cli/command/container/start.go index 5e4d612987..7912f1a196 100644 --- a/cli/command/container/start.go +++ b/cli/command/container/start.go @@ -116,7 +116,7 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er if errAttach != nil { return errAttach } - defer resp.Close() + defer resp.HijackedResponse.Close() cErr := make(chan error, 1) @@ -127,7 +127,7 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er inputStream: in, outputStream: dockerCli.Out(), errorStream: dockerCli.Err(), - resp: resp, + resp: resp.HijackedResponse, tty: c.Config.Tty, detachKeys: options.DetachKeys, } @@ -166,7 +166,8 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er } } if attachErr := <-cErr; attachErr != nil { - if _, ok := attachErr.(term.EscapeError); ok { + var escapeError term.EscapeError + if errors.As(attachErr, &escapeError) { // The user entered the detach escape sequence. return nil } diff --git a/cli/command/formatter/volume.go b/cli/command/formatter/volume.go index 584ca89bf2..e3d4b1922d 100644 --- a/cli/command/formatter/volume.go +++ b/cli/command/formatter/volume.go @@ -40,10 +40,10 @@ func NewVolumeFormat(source string, quiet bool) Format { } // VolumeWrite writes formatted volumes using the Context -func VolumeWrite(ctx Context, volumes []*volume.Volume) error { +func VolumeWrite(ctx Context, volumes []volume.Volume) error { render := func(format func(subContext SubContext) error) error { for _, vol := range volumes { - if err := format(&volumeContext{v: *vol}); err != nil { + if err := format(&volumeContext{v: vol}); err != nil { return err } } diff --git a/cli/command/formatter/volume_test.go b/cli/command/formatter/volume_test.go index f0569cc136..c25044c048 100644 --- a/cli/command/formatter/volume_test.go +++ b/cli/command/formatter/volume_test.go @@ -124,7 +124,7 @@ foobar_bar }, } - volumes := []*volume.Volume{ + volumes := []volume.Volume{ {Name: "foobar_baz", Driver: "foo"}, {Name: "foobar_bar", Driver: "bar"}, } @@ -144,7 +144,7 @@ foobar_bar } func TestVolumeContextWriteJSON(t *testing.T) { - volumes := []*volume.Volume{ + volumes := []volume.Volume{ {Driver: "foo", Name: "foobar_baz"}, {Driver: "bar", Name: "foobar_bar"}, } @@ -167,7 +167,7 @@ func TestVolumeContextWriteJSON(t *testing.T) { } func TestVolumeContextWriteJSONField(t *testing.T) { - volumes := []*volume.Volume{ + volumes := []volume.Volume{ {Driver: "foo", Name: "foobar_baz"}, {Driver: "bar", Name: "foobar_bar"}, } diff --git a/cli/command/image/import_test.go b/cli/command/image/import_test.go index cb75769c41..131233a235 100644 --- a/cli/command/image/import_test.go +++ b/cli/command/image/import_test.go @@ -50,7 +50,6 @@ func TestNewImportCommandInvalidFile(t *testing.T) { } func TestNewImportCommandSuccess(t *testing.T) { - t.Skip("FIXME(thaJeztah): how to mock this?") testCases := []struct { name string args []string diff --git a/cli/command/image/load_test.go b/cli/command/image/load_test.go index e81f8c671d..0140012cf1 100644 --- a/cli/command/image/load_test.go +++ b/cli/command/image/load_test.go @@ -97,7 +97,7 @@ func TestNewLoadCommandSuccess(t *testing.T) { // Body: io.NopCloser(strings.NewReader(`{"ID": "1"}`)), // JSON: true, // }, nil - return client.ImageLoadResult{}, nil + return client.ImageLoadResult{JSON: true}, nil }, }, { diff --git a/cli/command/image/remove.go b/cli/command/image/remove.go index 28069c9209..ea9e513edc 100644 --- a/cli/command/image/remove.go +++ b/cli/command/image/remove.go @@ -86,7 +86,7 @@ func runRemove(ctx context.Context, dockerCLI command.Cli, opts removeOptions, i } errs = append(errs, err) } else { - for _, del := range res.Deleted { + for _, del := range res.Items { if del.Deleted != "" { _, _ = fmt.Fprintln(dockerCLI.Out(), "Deleted:", del.Deleted) } else { diff --git a/cli/command/image/remove_test.go b/cli/command/image/remove_test.go index 28ec4e932e..8d6ebe825d 100644 --- a/cli/command/image/remove_test.go +++ b/cli/command/image/remove_test.go @@ -88,7 +88,7 @@ func TestNewRemoveCommandSuccess(t *testing.T) { imageRemoveFunc: func(img string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error) { assert.Check(t, is.Equal("image1", img)) return client.ImageRemoveResult{ - Deleted: []image.DeleteResponse{{Deleted: img}}, + Items: []image.DeleteResponse{{Deleted: img}}, }, nil }, }, @@ -109,7 +109,7 @@ func TestNewRemoveCommandSuccess(t *testing.T) { imageRemoveFunc: func(img string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error) { assert.Check(t, is.Equal("image1", img)) return client.ImageRemoveResult{ - Deleted: []image.DeleteResponse{{Untagged: img}}, + Items: []image.DeleteResponse{{Untagged: img}}, }, nil }, }, @@ -119,11 +119,11 @@ func TestNewRemoveCommandSuccess(t *testing.T) { imageRemoveFunc: func(img string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error) { if img == "image1" { return client.ImageRemoveResult{ - Deleted: []image.DeleteResponse{{Untagged: img}}, + Items: []image.DeleteResponse{{Untagged: img}}, }, nil } return client.ImageRemoveResult{ - Deleted: []image.DeleteResponse{{Deleted: img}}, + Items: []image.DeleteResponse{{Deleted: img}}, }, nil }, }, diff --git a/cli/command/node/demote_test.go b/cli/command/node/demote_test.go index 97a92883bb..494de911e4 100644 --- a/cli/command/node/demote_test.go +++ b/cli/command/node/demote_test.go @@ -59,8 +59,8 @@ func TestNodeDemoteNoChange(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if options.Node.Role != swarm.NodeRoleWorker { - return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Node.Role)) + if options.Spec.Role != swarm.NodeRoleWorker { + return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Spec.Role)) } return client.NodeUpdateResult{}, nil }, @@ -78,8 +78,8 @@ func TestNodeDemoteMultipleNode(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if options.Node.Role != swarm.NodeRoleWorker { - return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Node.Role)) + if options.Spec.Role != swarm.NodeRoleWorker { + return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Spec.Role)) } return client.NodeUpdateResult{}, nil }, diff --git a/cli/command/node/promote_test.go b/cli/command/node/promote_test.go index 83bbabec3a..d91169acc4 100644 --- a/cli/command/node/promote_test.go +++ b/cli/command/node/promote_test.go @@ -59,8 +59,8 @@ func TestNodePromoteNoChange(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if options.Node.Role != swarm.NodeRoleManager { - return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Node.Role)) + if options.Spec.Role != swarm.NodeRoleManager { + return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Spec.Role)) } return client.NodeUpdateResult{}, nil }, @@ -78,8 +78,8 @@ func TestNodePromoteMultipleNode(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if options.Node.Role != swarm.NodeRoleManager { - return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Node.Role)) + if options.Spec.Role != swarm.NodeRoleManager { + return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Spec.Role)) } return client.NodeUpdateResult{}, nil }, diff --git a/cli/command/node/update.go b/cli/command/node/update.go index 874dca33cf..1bfd4949e2 100644 --- a/cli/command/node/update.go +++ b/cli/command/node/update.go @@ -66,7 +66,7 @@ func updateNodes(ctx context.Context, apiClient client.NodeAPIClient, nodes []st } _, err = apiClient.NodeUpdate(ctx, res.Node.ID, client.NodeUpdateOptions{ Version: res.Node.Version, - Node: res.Node.Spec, + Spec: res.Node.Spec, }) if err != nil { return err diff --git a/cli/command/node/update_test.go b/cli/command/node/update_test.go index fd1fbb4849..2ce4b65934 100644 --- a/cli/command/node/update_test.go +++ b/cli/command/node/update_test.go @@ -91,8 +91,8 @@ func TestNodeUpdate(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if options.Node.Role != swarm.NodeRoleManager { - return client.NodeUpdateResult{}, errors.New("expected role manager, got " + string(options.Node.Role)) + if options.Spec.Role != swarm.NodeRoleManager { + return client.NodeUpdateResult{}, errors.New("expected role manager, got " + string(options.Spec.Role)) } return client.NodeUpdateResult{}, nil }, @@ -108,8 +108,8 @@ func TestNodeUpdate(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if options.Node.Availability != swarm.NodeAvailabilityDrain { - return client.NodeUpdateResult{}, errors.New("expected drain availability, got " + string(options.Node.Availability)) + if options.Spec.Availability != swarm.NodeAvailabilityDrain { + return client.NodeUpdateResult{}, errors.New("expected drain availability, got " + string(options.Spec.Availability)) } return client.NodeUpdateResult{}, nil }, @@ -125,8 +125,8 @@ func TestNodeUpdate(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if _, present := options.Node.Annotations.Labels["lbl"]; !present { - return client.NodeUpdateResult{}, fmt.Errorf("expected 'lbl' label, got %v", options.Node.Annotations.Labels) + if _, present := options.Spec.Annotations.Labels["lbl"]; !present { + return client.NodeUpdateResult{}, fmt.Errorf("expected 'lbl' label, got %v", options.Spec.Annotations.Labels) } return client.NodeUpdateResult{}, nil }, @@ -142,8 +142,8 @@ func TestNodeUpdate(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if value, present := options.Node.Annotations.Labels["key"]; !present || value != "value" { - return client.NodeUpdateResult{}, fmt.Errorf("expected 'key' label to be 'value', got %v", options.Node.Annotations.Labels) + if value, present := options.Spec.Annotations.Labels["key"]; !present || value != "value" { + return client.NodeUpdateResult{}, fmt.Errorf("expected 'key' label to be 'value', got %v", options.Spec.Annotations.Labels) } return client.NodeUpdateResult{}, nil }, @@ -161,8 +161,8 @@ func TestNodeUpdate(t *testing.T) { }, nil }, nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) { - if len(options.Node.Annotations.Labels) > 0 { - return client.NodeUpdateResult{}, fmt.Errorf("expected no labels, got %v", options.Node.Annotations.Labels) + if len(options.Spec.Annotations.Labels) > 0 { + return client.NodeUpdateResult{}, fmt.Errorf("expected no labels, got %v", options.Spec.Annotations.Labels) } return client.NodeUpdateResult{}, nil }, diff --git a/cli/command/plugin/client_test.go b/cli/command/plugin/client_test.go index feefb90489..455af0b433 100644 --- a/cli/command/plugin/client_test.go +++ b/cli/command/plugin/client_test.go @@ -3,6 +3,7 @@ package plugin import ( "context" "io" + "strings" "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" @@ -78,5 +79,5 @@ func (c *fakeClient) PluginUpgrade(_ context.Context, name string, options clien return c.pluginUpgradeFunc(name, options) } // FIXME(thaJeztah): how to mock this? - return nil, nil + return io.NopCloser(strings.NewReader("")), nil } diff --git a/cli/command/service/client_test.go b/cli/command/service/client_test.go index 8573b546e3..0e72b13a89 100644 --- a/cli/command/service/client_test.go +++ b/cli/command/service/client_test.go @@ -12,7 +12,7 @@ import ( type fakeClient struct { client.Client serviceInspectFunc func(ctx context.Context, serviceID string, options client.ServiceInspectOptions) (client.ServiceInspectResult, error) - serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) + serviceUpdateFunc func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) serviceListFunc func(context.Context, client.ServiceListOptions) (client.ServiceListResult, error) taskListFunc func(context.Context, client.TaskListOptions) (client.TaskListResult, error) infoFunc func(ctx context.Context) (system.Info, error) @@ -52,9 +52,9 @@ func (f *fakeClient) ServiceList(ctx context.Context, options client.ServiceList return client.ServiceListResult{}, nil } -func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { +func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { if f.serviceUpdateFunc != nil { - return f.serviceUpdateFunc(ctx, serviceID, version, service, options) + return f.serviceUpdateFunc(ctx, serviceID, options) } return client.ServiceUpdateResult{}, nil diff --git a/cli/command/service/create.go b/cli/command/service/create.go index c3c9565b19..cea9a91d1b 100644 --- a/cli/command/service/create.go +++ b/cli/command/service/create.go @@ -95,7 +95,6 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command { func runCreate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opts *serviceOptions) error { apiClient := dockerCLI.Client() - createOpts := client.ServiceCreateOptions{} service, err := opts.ToService(ctx, apiClient, flags) if err != nil { @@ -121,19 +120,22 @@ func runCreate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, } // only send auth if flag was set + var encodedAuth string if opts.registryAuth { // Retrieve encoded auth token from the image reference - encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), opts.image) + var err error + encodedAuth, err = command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), opts.image) if err != nil { return err } - createOpts.EncodedRegistryAuth = encodedAuth } - // query registry if flag disabling it was not set - createOpts.QueryRegistry = !opts.noResolveImage + response, err := apiClient.ServiceCreate(ctx, client.ServiceCreateOptions{ + Spec: service, - response, err := apiClient.ServiceCreate(ctx, service, createOpts) + EncodedRegistryAuth: encodedAuth, + QueryRegistry: !opts.noResolveImage, // query registry if flag disabling it was not set. + }) if err != nil { return err } diff --git a/cli/command/service/rollback.go b/cli/command/service/rollback.go index f99c83fdf6..e3ca98e238 100644 --- a/cli/command/service/rollback.go +++ b/cli/command/service/rollback.go @@ -40,7 +40,9 @@ func runRollback(ctx context.Context, dockerCLI command.Cli, options *serviceOpt return err } - response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, res.Service.Version, res.Service.Spec, client.ServiceUpdateOptions{ + response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, client.ServiceUpdateOptions{ + Version: res.Service.Version, + Spec: res.Service.Spec, Rollback: "previous", // TODO(thaJeztah): this should have a const defined }) if err != nil { diff --git a/cli/command/service/rollback_test.go b/cli/command/service/rollback_test.go index e41904c383..19842888ba 100644 --- a/cli/command/service/rollback_test.go +++ b/cli/command/service/rollback_test.go @@ -8,7 +8,6 @@ import ( "testing" "github.com/docker/cli/internal/test" - "github.com/moby/moby/api/types/swarm" "github.com/moby/moby/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -18,7 +17,7 @@ func TestRollback(t *testing.T) { testCases := []struct { name string args []string - serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) + serviceUpdateFunc func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) expectedDockerCliErr string }{ { @@ -28,7 +27,7 @@ func TestRollback(t *testing.T) { { name: "rollback-service-with-warnings", args: []string{"service-id"}, - serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { + serviceUpdateFunc: func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { return client.ServiceUpdateResult{ Warnings: []string{ "- warning 1", @@ -59,7 +58,7 @@ func TestRollbackWithErrors(t *testing.T) { name string args []string serviceInspectFunc func(ctx context.Context, serviceID string, options client.ServiceInspectOptions) (client.ServiceInspectResult, error) - serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, opts client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) + serviceUpdateFunc func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) expectedError string }{ { @@ -82,7 +81,7 @@ func TestRollbackWithErrors(t *testing.T) { { name: "service-update-failed", args: []string{"service-id"}, - serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { + serviceUpdateFunc: func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { return client.ServiceUpdateResult{}, fmt.Errorf("no such services: %s", serviceID) }, expectedError: "no such services: service-id", diff --git a/cli/command/service/scale.go b/cli/command/service/scale.go index 8f3df7b2db..a2555ab98f 100644 --- a/cli/command/service/scale.go +++ b/cli/command/service/scale.go @@ -108,7 +108,10 @@ func runServiceScale(ctx context.Context, apiClient client.ServiceAPIClient, ser return nil, errors.New("scale can only be used with replicated or replicated-job mode") } - response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, res.Service.Version, res.Service.Spec, client.ServiceUpdateOptions{}) + response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, client.ServiceUpdateOptions{ + Version: res.Service.Version, + Spec: res.Service.Spec, + }) if err != nil { return nil, err } diff --git a/cli/command/service/update.go b/cli/command/service/update.go index fa4ae5dd22..38913e3d2b 100644 --- a/cli/command/service/update.go +++ b/cli/command/service/update.go @@ -46,14 +46,14 @@ func newUpdateCommand(dockerCLI command.Cli) *cobra.Command { flags.String("image", "", "Service image tag") flags.Var(&ShlexOpt{}, "args", "Service command args") flags.Bool(flagRollback, false, "Rollback to previous specification") - flags.SetAnnotation(flagRollback, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagRollback, "version", []string{"1.25"}) flags.Bool("force", false, "Force update even if no changes require it") - flags.SetAnnotation("force", "version", []string{"1.25"}) + _ = flags.SetAnnotation("force", "version", []string{"1.25"}) addServiceFlags(flags, options, nil) flags.Var(newListOptsVar(), flagEnvRemove, "Remove an environment variable") flags.Var(newListOptsVar(), flagGroupRemove, "Remove a previously added supplementary user group from the container") - flags.SetAnnotation(flagGroupRemove, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagGroupRemove, "version", []string{"1.25"}) flags.Var(newListOptsVar(), flagLabelRemove, "Remove a label by its key") flags.Var(newListOptsVar(), flagContainerLabelRemove, "Remove a container label by its key") flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path") @@ -61,65 +61,65 @@ func newUpdateCommand(dockerCLI command.Cli) *cobra.Command { flags.Var(&swarmopts.PortOpt{}, flagPublishRemove, "Remove a published port by its target port") flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint") flags.Var(newListOptsVar(), flagDNSRemove, "Remove a custom DNS server") - flags.SetAnnotation(flagDNSRemove, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagDNSRemove, "version", []string{"1.25"}) flags.Var(newListOptsVar(), flagDNSOptionRemove, "Remove a DNS option") - flags.SetAnnotation(flagDNSOptionRemove, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagDNSOptionRemove, "version", []string{"1.25"}) flags.Var(newListOptsVar(), flagDNSSearchRemove, "Remove a DNS search domain") - flags.SetAnnotation(flagDNSSearchRemove, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagDNSSearchRemove, "version", []string{"1.25"}) flags.Var(newListOptsVar(), flagHostRemove, `Remove a custom host-to-IP mapping ("host:ip")`) - flags.SetAnnotation(flagHostRemove, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagHostRemove, "version", []string{"1.25"}) flags.Var(&options.labels, flagLabelAdd, "Add or update a service label") flags.Var(&options.containerLabels, flagContainerLabelAdd, "Add or update a container label") flags.Var(&options.env, flagEnvAdd, "Add or update an environment variable") flags.Var(newListOptsVar(), flagSecretRemove, "Remove a secret") - flags.SetAnnotation(flagSecretRemove, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagSecretRemove, "version", []string{"1.25"}) flags.Var(&options.secrets, flagSecretAdd, "Add or update a secret on a service") - flags.SetAnnotation(flagSecretAdd, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagSecretAdd, "version", []string{"1.25"}) flags.Var(newListOptsVar(), flagConfigRemove, "Remove a configuration file") - flags.SetAnnotation(flagConfigRemove, "version", []string{"1.30"}) + _ = flags.SetAnnotation(flagConfigRemove, "version", []string{"1.30"}) flags.Var(&options.configs, flagConfigAdd, "Add or update a config file on a service") - flags.SetAnnotation(flagConfigAdd, "version", []string{"1.30"}) + _ = flags.SetAnnotation(flagConfigAdd, "version", []string{"1.30"}) flags.Var(&options.mounts, flagMountAdd, "Add or update a mount on a service") flags.Var(&options.constraints, flagConstraintAdd, "Add or update a placement constraint") flags.Var(&options.placementPrefs, flagPlacementPrefAdd, "Add a placement preference") - flags.SetAnnotation(flagPlacementPrefAdd, "version", []string{"1.28"}) + _ = flags.SetAnnotation(flagPlacementPrefAdd, "version", []string{"1.28"}) flags.Var(&placementPrefOpts{}, flagPlacementPrefRemove, "Remove a placement preference") - flags.SetAnnotation(flagPlacementPrefRemove, "version", []string{"1.28"}) + _ = flags.SetAnnotation(flagPlacementPrefRemove, "version", []string{"1.28"}) flags.Var(&options.networks, flagNetworkAdd, "Add a network") - flags.SetAnnotation(flagNetworkAdd, "version", []string{"1.29"}) + _ = flags.SetAnnotation(flagNetworkAdd, "version", []string{"1.29"}) flags.Var(newListOptsVar(), flagNetworkRemove, "Remove a network") - flags.SetAnnotation(flagNetworkRemove, "version", []string{"1.29"}) + _ = flags.SetAnnotation(flagNetworkRemove, "version", []string{"1.29"}) flags.Var(&options.endpoint.publishPorts, flagPublishAdd, "Add or update a published port") flags.Var(&options.groups, flagGroupAdd, "Add an additional supplementary user group to the container") - flags.SetAnnotation(flagGroupAdd, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagGroupAdd, "version", []string{"1.25"}) flags.Var(&options.dns, flagDNSAdd, "Add or update a custom DNS server") - flags.SetAnnotation(flagDNSAdd, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagDNSAdd, "version", []string{"1.25"}) flags.Var(&options.dnsOption, flagDNSOptionAdd, "Add or update a DNS option") - flags.SetAnnotation(flagDNSOptionAdd, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagDNSOptionAdd, "version", []string{"1.25"}) flags.Var(&options.dnsSearch, flagDNSSearchAdd, "Add or update a custom DNS search domain") - flags.SetAnnotation(flagDNSSearchAdd, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagDNSSearchAdd, "version", []string{"1.25"}) flags.Var(&options.hosts, flagHostAdd, `Add a custom host-to-IP mapping ("host:ip")`) - flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"}) + _ = flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"}) flags.BoolVar(&options.init, flagInit, false, "Use an init inside each service container to forward signals and reap processes") - flags.SetAnnotation(flagInit, "version", []string{"1.37"}) + _ = flags.SetAnnotation(flagInit, "version", []string{"1.37"}) flags.Var(&options.sysctls, flagSysCtlAdd, "Add or update a Sysctl option") - flags.SetAnnotation(flagSysCtlAdd, "version", []string{"1.40"}) + _ = flags.SetAnnotation(flagSysCtlAdd, "version", []string{"1.40"}) flags.Var(newListOptsVar(), flagSysCtlRemove, "Remove a Sysctl option") - flags.SetAnnotation(flagSysCtlRemove, "version", []string{"1.40"}) + _ = flags.SetAnnotation(flagSysCtlRemove, "version", []string{"1.40"}) flags.Var(&options.ulimits, flagUlimitAdd, "Add or update a ulimit option") - flags.SetAnnotation(flagUlimitAdd, "version", []string{"1.41"}) + _ = flags.SetAnnotation(flagUlimitAdd, "version", []string{"1.41"}) flags.Var(newListOptsVar(), flagUlimitRemove, "Remove a ulimit option") - flags.SetAnnotation(flagUlimitRemove, "version", []string{"1.41"}) + _ = flags.SetAnnotation(flagUlimitRemove, "version", []string{"1.41"}) flags.Int64Var(&options.oomScoreAdj, flagOomScoreAdj, 0, "Tune host's OOM preferences (-1000 to 1000) ") - flags.SetAnnotation(flagOomScoreAdj, "version", []string{"1.46"}) + _ = flags.SetAnnotation(flagOomScoreAdj, "version", []string{"1.46"}) // Add needs parsing, Remove only needs the key flags.Var(newListOptsVar(), flagGenericResourcesRemove, "Remove a Generic resource") - flags.SetAnnotation(flagGenericResourcesRemove, "version", []string{"1.32"}) + _ = flags.SetAnnotation(flagGenericResourcesRemove, "version", []string{"1.32"}) flags.Var(newListOptsVarWithValidator(ValidateSingleGenericResource), flagGenericResourcesAdd, "Add a Generic resource") - flags.SetAnnotation(flagGenericResourcesAdd, "version", []string{"1.32"}) + _ = flags.SetAnnotation(flagGenericResourcesAdd, "version", []string{"1.32"}) // TODO(thaJeztah): add completion for capabilities, stop-signal (currently non-exported in container package) // _ = cmd.RegisterFlagCompletionFunc(flagCapAdd, completeLinuxCapabilityNames) @@ -164,7 +164,6 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, return err } - spec := &res.Service.Spec if rollback { // Rollback can't be combined with other flags. otherFlagsPassed := false @@ -182,10 +181,12 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, } updateOpts := client.ServiceUpdateOptions{} + rollbackAction := "none" if rollback { - updateOpts.Rollback = "previous" + rollbackAction = "previous" } + spec := &res.Service.Spec err = updateService(ctx, apiClient, flags, spec) if err != nil { return err @@ -202,14 +203,12 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, if err != nil { return err } - spec.TaskTemplate.ContainerSpec.Secrets = updatedSecrets updatedConfigs, err := getUpdatedConfigs(ctx, apiClient, flags, spec.TaskTemplate.ContainerSpec) if err != nil { return err } - spec.TaskTemplate.ContainerSpec.Configs = updatedConfigs // set the credential spec value after get the updated configs, because we @@ -218,24 +217,31 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, updateCredSpecConfig(flags, spec.TaskTemplate.ContainerSpec) // only send auth if flag was set - sendAuth, err := flags.GetBool(flagRegistryAuth) - if err != nil { + var encodedAuth string + var registryAuthFrom string + if ok, err := flags.GetBool(flagRegistryAuth); err != nil { return err - } - if sendAuth { + } else if ok { // Retrieve encoded auth token from the image reference // This would be the old image if it didn't change in this update - image := spec.TaskTemplate.ContainerSpec.Image - encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), image) + var err error + encodedAuth, err = command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), spec.TaskTemplate.ContainerSpec.Image) if err != nil { return err } updateOpts.EncodedRegistryAuth = encodedAuth } else { - updateOpts.RegistryAuthFrom = swarm.RegistryAuthFromSpec + registryAuthFrom = swarm.RegistryAuthFromSpec } - response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, res.Service.Version, *spec, updateOpts) + response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, client.ServiceUpdateOptions{ + Version: res.Service.Version, + Spec: *spec, + + EncodedRegistryAuth: encodedAuth, + RegistryAuthFrom: registryAuthFrom, + Rollback: rollbackAction, + }) if err != nil { return err } diff --git a/cli/command/stack/client_test.go b/cli/command/stack/client_test.go index 95b2717405..2855583f5b 100644 --- a/cli/command/stack/client_test.go +++ b/cli/command/stack/client_test.go @@ -31,7 +31,7 @@ type fakeClient struct { nodeListFunc func(options client.NodeListOptions) (client.NodeListResult, error) taskListFunc func(options client.TaskListOptions) (client.TaskListResult, error) nodeInspectFunc func(ref string) (client.NodeInspectResult, error) - serviceUpdateFunc func(serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) + serviceUpdateFunc func(serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) serviceRemoveFunc func(serviceID string) (client.ServiceRemoveResult, error) networkRemoveFunc func(networkID string) error secretRemoveFunc func(secretID string) (client.SecretRemoveResult, error) @@ -130,9 +130,9 @@ func (cli *fakeClient) NodeInspect(_ context.Context, ref string, _ client.NodeI return client.NodeInspectResult{}, nil } -func (cli *fakeClient) ServiceUpdate(_ context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { +func (cli *fakeClient) ServiceUpdate(_ context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { if cli.serviceUpdateFunc != nil { - return cli.serviceUpdateFunc(serviceID, version, service, options) + return cli.serviceUpdateFunc(serviceID, options) } return client.ServiceUpdateResult{}, nil diff --git a/cli/command/stack/deploy_composefile.go b/cli/command/stack/deploy_composefile.go index a6c190881f..ad85765133 100644 --- a/cli/command/stack/deploy_composefile.go +++ b/cli/command/stack/deploy_composefile.go @@ -233,7 +233,10 @@ func deployServices(ctx context.Context, dockerCLI command.Cli, services map[str if svc, exists := existingServiceMap[name]; exists { _, _ = fmt.Fprintf(out, "Updating service %s (id: %s)\n", name, svc.ID) - updateOpts := client.ServiceUpdateOptions{EncodedRegistryAuth: encodedAuth} + updateOpts := client.ServiceUpdateOptions{ + Version: svc.Version, + EncodedRegistryAuth: encodedAuth, + } switch resolveImage { case resolveImageAlways: @@ -265,7 +268,8 @@ func deployServices(ctx context.Context, dockerCLI command.Cli, services map[str // TODO move this to API client? serviceSpec.TaskTemplate.ForceUpdate = svc.Spec.TaskTemplate.ForceUpdate - response, err := apiClient.ServiceUpdate(ctx, svc.ID, svc.Version, serviceSpec, updateOpts) + updateOpts.Spec = serviceSpec + response, err := apiClient.ServiceUpdate(ctx, svc.ID, updateOpts) if err != nil { return nil, fmt.Errorf("failed to update service %s: %w", name, err) } @@ -281,7 +285,8 @@ func deployServices(ctx context.Context, dockerCLI command.Cli, services map[str // query registry if flag disabling it was not set queryRegistry := resolveImage == resolveImageAlways || resolveImage == resolveImageChanged - response, err := apiClient.ServiceCreate(ctx, serviceSpec, client.ServiceCreateOptions{ + response, err := apiClient.ServiceCreate(ctx, client.ServiceCreateOptions{ + Spec: serviceSpec, EncodedRegistryAuth: encodedAuth, QueryRegistry: queryRegistry, }) diff --git a/cli/command/stack/deploy_test.go b/cli/command/stack/deploy_test.go index 6aad4d0e4b..a0fb1fd0c4 100644 --- a/cli/command/stack/deploy_test.go +++ b/cli/command/stack/deploy_test.go @@ -42,10 +42,7 @@ func TestPruneServices(t *testing.T) { func TestServiceUpdateResolveImageChanged(t *testing.T) { namespace := convert.NewNamespace("mystack") - var ( - receivedOptions client.ServiceUpdateOptions - receivedService swarm.ServiceSpec - ) + var receivedOptions client.ServiceUpdateOptions fakeCli := test.NewFakeCli(&fakeClient{ serviceListFunc: func(options client.ServiceListOptions) (client.ServiceListResult, error) { @@ -68,9 +65,8 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) { }, }, nil }, - serviceUpdateFunc: func(serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { + serviceUpdateFunc: func(serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) { receivedOptions = options - receivedService = service return client.ServiceUpdateResult{}, nil }, }) @@ -113,10 +109,9 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) { _, err := deployServices(ctx, fakeCli, spec, namespace, false, resolveImageChanged) assert.NilError(t, err) assert.Check(t, is.Equal(receivedOptions.QueryRegistry, tc.expectedQueryRegistry)) - assert.Check(t, is.Equal(receivedService.TaskTemplate.ContainerSpec.Image, tc.expectedImage)) - assert.Check(t, is.Equal(receivedService.TaskTemplate.ForceUpdate, tc.expectedForceUpdate)) + assert.Check(t, is.Equal(receivedOptions.Spec.TaskTemplate.ContainerSpec.Image, tc.expectedImage)) + assert.Check(t, is.Equal(receivedOptions.Spec.TaskTemplate.ForceUpdate, tc.expectedForceUpdate)) - receivedService = swarm.ServiceSpec{} receivedOptions = client.ServiceUpdateOptions{} }) } diff --git a/cli/command/swarm/ca.go b/cli/command/swarm/ca.go index 2e4578d0ad..749afd860d 100644 --- a/cli/command/swarm/ca.go +++ b/cli/command/swarm/ca.go @@ -84,8 +84,9 @@ func runCA(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opt } updateSwarmSpec(&res.Swarm.Spec, flags, opts) - if _, err := apiClient.SwarmUpdate(ctx, res.Swarm.Version, client.SwarmUpdateOptions{ - Swarm: res.Swarm.Spec, + if _, err := apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{ + Version: res.Swarm.Version, + Spec: res.Swarm.Spec, }); err != nil { return err } diff --git a/cli/command/swarm/ca_test.go b/cli/command/swarm/ca_test.go index 904f405ee3..870f9b49f2 100644 --- a/cli/command/swarm/ca_test.go +++ b/cli/command/swarm/ca_test.go @@ -173,7 +173,7 @@ type swarmUpdateRecorder struct { } func (s *swarmUpdateRecorder) swarmUpdate(opts client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) { - s.spec = opts.Swarm + s.spec = opts.Spec return client.SwarmUpdateResult{}, nil } diff --git a/cli/command/swarm/client_test.go b/cli/command/swarm/client_test.go index 8682a5827e..8c5a42a881 100644 --- a/cli/command/swarm/client_test.go +++ b/cli/command/swarm/client_test.go @@ -3,7 +3,6 @@ package swarm import ( "context" - "github.com/moby/moby/api/types/swarm" "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) @@ -70,7 +69,7 @@ func (cli *fakeClient) SwarmLeave(context.Context, client.SwarmLeaveOptions) (cl return client.SwarmLeaveResult{}, nil } -func (cli *fakeClient) SwarmUpdate(_ context.Context, _ swarm.Version, options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) { +func (cli *fakeClient) SwarmUpdate(_ context.Context, options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) { if cli.swarmUpdateFunc != nil { return cli.swarmUpdateFunc(options) } diff --git a/cli/command/swarm/join_token.go b/cli/command/swarm/join_token.go index 364f616027..4639035c78 100644 --- a/cli/command/swarm/join_token.go +++ b/cli/command/swarm/join_token.go @@ -58,8 +58,9 @@ func runJoinToken(ctx context.Context, dockerCLI command.Cli, opts joinTokenOpti return err } - _, err = apiClient.SwarmUpdate(ctx, res.Swarm.Version, client.SwarmUpdateOptions{ - Swarm: res.Swarm.Spec, + _, err = apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{ + Version: res.Swarm.Version, + Spec: res.Swarm.Spec, RotateWorkerToken: worker, RotateManagerToken: manager, }) diff --git a/cli/command/swarm/unlock_key.go b/cli/command/swarm/unlock_key.go index 6e6cba2b19..a8df5089e5 100644 --- a/cli/command/swarm/unlock_key.go +++ b/cli/command/swarm/unlock_key.go @@ -55,8 +55,10 @@ func runUnlockKey(ctx context.Context, dockerCLI command.Cli, opts unlockKeyOpti return errors.New("cannot rotate because autolock is not turned on") } - _, err = apiClient.SwarmUpdate(ctx, res.Swarm.Version, client.SwarmUpdateOptions{ - Swarm: res.Swarm.Spec, + _, err = apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{ + Version: res.Swarm.Version, + Spec: res.Swarm.Spec, + RotateManagerUnlockKey: true, }) if err != nil { diff --git a/cli/command/swarm/update.go b/cli/command/swarm/update.go index c691a7fc9c..9dc373211a 100644 --- a/cli/command/swarm/update.go +++ b/cli/command/swarm/update.go @@ -54,8 +54,9 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, curAutoLock := sw.Swarm.Spec.EncryptionConfig.AutoLockManagers - _, err = apiClient.SwarmUpdate(ctx, sw.Swarm.Version, client.SwarmUpdateOptions{ - Swarm: sw.Swarm.Spec, + _, err = apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{ + Version: sw.Swarm.Version, + Spec: sw.Swarm.Spec, }) if err != nil { return err diff --git a/cli/command/swarm/update_test.go b/cli/command/swarm/update_test.go index 58cf9febb1..c611b269f9 100644 --- a/cli/command/swarm/update_test.go +++ b/cli/command/swarm/update_test.go @@ -120,33 +120,33 @@ func TestSwarmUpdate(t *testing.T) { }, nil }, swarmUpdateFunc: func(options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) { - if *options.Swarm.Orchestration.TaskHistoryRetentionLimit != 10 { + if *options.Spec.Orchestration.TaskHistoryRetentionLimit != 10 { return client.SwarmUpdateResult{}, errors.New("historyLimit not correctly set") } heartbeatDuration, err := time.ParseDuration("10s") if err != nil { return client.SwarmUpdateResult{}, err } - if options.Swarm.Dispatcher.HeartbeatPeriod != heartbeatDuration { + if options.Spec.Dispatcher.HeartbeatPeriod != heartbeatDuration { return client.SwarmUpdateResult{}, errors.New("heartbeatPeriodLimit not correctly set") } certExpiryDuration, err := time.ParseDuration("20s") if err != nil { return client.SwarmUpdateResult{}, err } - if options.Swarm.CAConfig.NodeCertExpiry != certExpiryDuration { + if options.Spec.CAConfig.NodeCertExpiry != certExpiryDuration { return client.SwarmUpdateResult{}, errors.New("certExpiry not correctly set") } - if len(options.Swarm.CAConfig.ExternalCAs) != 1 || options.Swarm.CAConfig.ExternalCAs[0].CACert != "trust-root" { + if len(options.Spec.CAConfig.ExternalCAs) != 1 || options.Spec.CAConfig.ExternalCAs[0].CACert != "trust-root" { return client.SwarmUpdateResult{}, errors.New("externalCA not correctly set") } - if *options.Swarm.Raft.KeepOldSnapshots != 10 { + if *options.Spec.Raft.KeepOldSnapshots != 10 { return client.SwarmUpdateResult{}, errors.New("keepOldSnapshots not correctly set") } - if options.Swarm.Raft.SnapshotInterval != 100 { + if options.Spec.Raft.SnapshotInterval != 100 { return client.SwarmUpdateResult{}, errors.New("snapshotInterval not correctly set") } - if !options.Swarm.EncryptionConfig.AutoLockManagers { + if !options.Spec.EncryptionConfig.AutoLockManagers { return client.SwarmUpdateResult{}, errors.New("auto-lock not correctly set") } return client.SwarmUpdateResult{}, nil @@ -159,7 +159,7 @@ func TestSwarmUpdate(t *testing.T) { flagAutolock: "true", }, swarmUpdateFunc: func(options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) { - if *options.Swarm.Orchestration.TaskHistoryRetentionLimit != 10 { + if *options.Spec.Orchestration.TaskHistoryRetentionLimit != 10 { return client.SwarmUpdateResult{}, errors.New("historyLimit not correctly set") } return client.SwarmUpdateResult{}, nil diff --git a/cli/command/system/completion.go b/cli/command/system/completion.go index 122aaf0bf6..55540de078 100644 --- a/cli/command/system/completion.go +++ b/cli/command/system/completion.go @@ -309,8 +309,8 @@ func volumeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []s if err != nil { return []string{} } - names := make([]string, 0, len(res.Items.Volumes)) - for _, v := range res.Items.Volumes { + names := make([]string, 0, len(res.Items)) + for _, v := range res.Items { names = append(names, v.Name) } return names diff --git a/cli/command/system/completion_test.go b/cli/command/system/completion_test.go index d6acacc897..48890dc710 100644 --- a/cli/command/system/completion_test.go +++ b/cli/command/system/completion_test.go @@ -139,11 +139,9 @@ func TestCompleteEventFilter(t *testing.T) { client: &fakeClient{ volumeListFunc: func(ctx context.Context, options client.VolumeListOptions) (client.VolumeListResult, error) { return client.VolumeListResult{ - Items: volume.ListResponse{ - Volumes: []*volume.Volume{ - builders.Volume(builders.VolumeName("v1")), - builders.Volume(builders.VolumeName("v2")), - }, + Items: []volume.Volume{ + builders.Volume(builders.VolumeName("v1")), + builders.Volume(builders.VolumeName("v2")), }, }, nil }, diff --git a/cli/command/volume/inspect_test.go b/cli/command/volume/inspect_test.go index 90cd97349d..e56d0a4fab 100644 --- a/cli/command/volume/inspect_test.go +++ b/cli/command/volume/inspect_test.go @@ -84,7 +84,7 @@ func TestVolumeInspectWithoutFormat(t *testing.T) { return client.VolumeInspectResult{}, fmt.Errorf("invalid volumeID, expected %s, got %s", "foo", volumeID) } return client.VolumeInspectResult{ - Volume: *builders.Volume(), + Volume: builders.Volume(), }, nil }, }, @@ -93,7 +93,7 @@ func TestVolumeInspectWithoutFormat(t *testing.T) { args: []string{"foo", "bar"}, volumeInspectFunc: func(volumeID string) (client.VolumeInspectResult, error) { return client.VolumeInspectResult{ - Volume: *builders.Volume(builders.VolumeName(volumeID), builders.VolumeLabels(map[string]string{ + Volume: builders.Volume(builders.VolumeName(volumeID), builders.VolumeLabels(map[string]string{ "foo": "bar", })), }, nil @@ -114,7 +114,7 @@ func TestVolumeInspectWithoutFormat(t *testing.T) { func TestVolumeInspectWithFormat(t *testing.T) { volumeInspectFunc := func(volumeID string) (client.VolumeInspectResult, error) { return client.VolumeInspectResult{ - Volume: *builders.Volume(builders.VolumeLabels(map[string]string{ + Volume: builders.Volume(builders.VolumeLabels(map[string]string{ "foo": "bar", })), }, nil diff --git a/cli/command/volume/list.go b/cli/command/volume/list.go index 3d797111fa..1e0df1f84b 100644 --- a/cli/command/volume/list.go +++ b/cli/command/volume/list.go @@ -71,13 +71,13 @@ func runList(ctx context.Context, dockerCLI command.Cli, options listOptions) er // trick for filtering in place n := 0 - for _, vol := range res.Items.Volumes { + for _, vol := range res.Items { if vol.ClusterVolume != nil { - res.Items.Volumes[n] = vol + res.Items[n] = vol n++ } } - res.Items.Volumes = res.Items.Volumes[:n] + res.Items = res.Items[:n] if !options.quiet { format = clusterTableFormat } else { @@ -85,13 +85,13 @@ func runList(ctx context.Context, dockerCLI command.Cli, options listOptions) er } } - sort.Slice(res.Items.Volumes, func(i, j int) bool { - return sortorder.NaturalLess(res.Items.Volumes[i].Name, res.Items.Volumes[j].Name) + sort.Slice(res.Items, func(i, j int) bool { + return sortorder.NaturalLess(res.Items[i].Name, res.Items[j].Name) }) volumeCtx := formatter.Context{ Output: dockerCLI.Out(), Format: formatter.NewVolumeFormat(format, options.quiet), } - return formatter.VolumeWrite(volumeCtx, res.Items.Volumes) + return formatter.VolumeWrite(volumeCtx, res.Items) } diff --git a/cli/command/volume/list_test.go b/cli/command/volume/list_test.go index 7176c58e01..5535aafead 100644 --- a/cli/command/volume/list_test.go +++ b/cli/command/volume/list_test.go @@ -52,14 +52,12 @@ func TestVolumeListWithoutFormat(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) { return client.VolumeListResult{ - Items: volume.ListResponse{ - Volumes: []*volume.Volume{ - builders.Volume(), - builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")), - builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{ - "foo": "bar", - })), - }, + Items: []volume.Volume{ + builders.Volume(), + builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")), + builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{ + "foo": "bar", + })), }, }, nil }, @@ -73,14 +71,12 @@ func TestVolumeListWithConfigFormat(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) { return client.VolumeListResult{ - Items: volume.ListResponse{ - Volumes: []*volume.Volume{ - builders.Volume(), - builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")), - builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{ - "foo": "bar", - })), - }, + Items: []volume.Volume{ + builders.Volume(), + builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")), + builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{ + "foo": "bar", + })), }, }, nil }, @@ -97,14 +93,12 @@ func TestVolumeListWithFormat(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) { return client.VolumeListResult{ - Items: volume.ListResponse{ - Volumes: []*volume.Volume{ - builders.Volume(), - builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")), - builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{ - "foo": "bar", - })), - }, + Items: []volume.Volume{ + builders.Volume(), + builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")), + builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{ + "foo": "bar", + })), }, }, nil }, @@ -119,12 +113,10 @@ func TestVolumeListSortOrder(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) { return client.VolumeListResult{ - Items: volume.ListResponse{ - Volumes: []*volume.Volume{ - builders.Volume(builders.VolumeName("volume-2-foo")), - builders.Volume(builders.VolumeName("volume-10-foo")), - builders.Volume(builders.VolumeName("volume-1-foo")), - }, + Items: []volume.Volume{ + builders.Volume(builders.VolumeName("volume-2-foo")), + builders.Volume(builders.VolumeName("volume-10-foo")), + builders.Volume(builders.VolumeName("volume-1-foo")), }, }, nil }, @@ -139,101 +131,99 @@ func TestClusterVolumeList(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) { return client.VolumeListResult{ - Items: volume.ListResponse{ - Volumes: []*volume.Volume{ - { - Name: "volume1", - Scope: "global", - Driver: "driver1", - ClusterVolume: &volume.ClusterVolume{ - Spec: volume.ClusterVolumeSpec{ - Group: "group1", - AccessMode: &volume.AccessMode{ - Scope: volume.ScopeSingleNode, - Sharing: volume.SharingOneWriter, - MountVolume: &volume.TypeMount{}, - }, - Availability: volume.AvailabilityActive, + Items: []volume.Volume{ + { + Name: "volume1", + Scope: "global", + Driver: "driver1", + ClusterVolume: &volume.ClusterVolume{ + Spec: volume.ClusterVolumeSpec{ + Group: "group1", + AccessMode: &volume.AccessMode{ + Scope: volume.ScopeSingleNode, + Sharing: volume.SharingOneWriter, + MountVolume: &volume.TypeMount{}, }, + Availability: volume.AvailabilityActive, }, }, - { - Name: "volume2", - Scope: "global", - Driver: "driver1", - ClusterVolume: &volume.ClusterVolume{ - Spec: volume.ClusterVolumeSpec{ - Group: "group1", - AccessMode: &volume.AccessMode{ - Scope: volume.ScopeSingleNode, - Sharing: volume.SharingOneWriter, - MountVolume: &volume.TypeMount{}, - }, - Availability: volume.AvailabilityPause, - }, - Info: &volume.Info{ - CapacityBytes: 100000000, - VolumeID: "driver1vol2", - }, - }, - }, - { - Name: "volume3", - Scope: "global", - Driver: "driver2", - ClusterVolume: &volume.ClusterVolume{ - Spec: volume.ClusterVolumeSpec{ - Group: "group2", - AccessMode: &volume.AccessMode{ - Scope: volume.ScopeMultiNode, - Sharing: volume.SharingAll, - MountVolume: &volume.TypeMount{}, - }, - Availability: volume.AvailabilityActive, - }, - PublishStatus: []*volume.PublishStatus{ - { - NodeID: "nodeid1", - State: volume.StatePublished, - }, - }, - Info: &volume.Info{ - CapacityBytes: 100000000, - VolumeID: "driver1vol3", - }, - }, - }, - { - Name: "volume4", - Scope: "global", - Driver: "driver2", - ClusterVolume: &volume.ClusterVolume{ - Spec: volume.ClusterVolumeSpec{ - Group: "group2", - AccessMode: &volume.AccessMode{ - Scope: volume.ScopeMultiNode, - Sharing: volume.SharingAll, - MountVolume: &volume.TypeMount{}, - }, - Availability: volume.AvailabilityActive, - }, - PublishStatus: []*volume.PublishStatus{ - { - NodeID: "nodeid1", - State: volume.StatePublished, - }, { - NodeID: "nodeid2", - State: volume.StatePublished, - }, - }, - Info: &volume.Info{ - CapacityBytes: 100000000, - VolumeID: "driver1vol4", - }, - }, - }, - builders.Volume(builders.VolumeName("volume-local-1")), }, + { + Name: "volume2", + Scope: "global", + Driver: "driver1", + ClusterVolume: &volume.ClusterVolume{ + Spec: volume.ClusterVolumeSpec{ + Group: "group1", + AccessMode: &volume.AccessMode{ + Scope: volume.ScopeSingleNode, + Sharing: volume.SharingOneWriter, + MountVolume: &volume.TypeMount{}, + }, + Availability: volume.AvailabilityPause, + }, + Info: &volume.Info{ + CapacityBytes: 100000000, + VolumeID: "driver1vol2", + }, + }, + }, + { + Name: "volume3", + Scope: "global", + Driver: "driver2", + ClusterVolume: &volume.ClusterVolume{ + Spec: volume.ClusterVolumeSpec{ + Group: "group2", + AccessMode: &volume.AccessMode{ + Scope: volume.ScopeMultiNode, + Sharing: volume.SharingAll, + MountVolume: &volume.TypeMount{}, + }, + Availability: volume.AvailabilityActive, + }, + PublishStatus: []*volume.PublishStatus{ + { + NodeID: "nodeid1", + State: volume.StatePublished, + }, + }, + Info: &volume.Info{ + CapacityBytes: 100000000, + VolumeID: "driver1vol3", + }, + }, + }, + { + Name: "volume4", + Scope: "global", + Driver: "driver2", + ClusterVolume: &volume.ClusterVolume{ + Spec: volume.ClusterVolumeSpec{ + Group: "group2", + AccessMode: &volume.AccessMode{ + Scope: volume.ScopeMultiNode, + Sharing: volume.SharingAll, + MountVolume: &volume.TypeMount{}, + }, + Availability: volume.AvailabilityActive, + }, + PublishStatus: []*volume.PublishStatus{ + { + NodeID: "nodeid1", + State: volume.StatePublished, + }, { + NodeID: "nodeid2", + State: volume.StatePublished, + }, + }, + Info: &volume.Info{ + CapacityBytes: 100000000, + VolumeID: "driver1vol4", + }, + }, + }, + builders.Volume(builders.VolumeName("volume-local-1")), }, }, nil }, diff --git a/cli/compose/loader/loader.go b/cli/compose/loader/loader.go index 92fff4fa27..8f1c62434a 100644 --- a/cli/compose/loader/loader.go +++ b/cli/compose/loader/loader.go @@ -26,7 +26,7 @@ import ( "github.com/go-viper/mapstructure/v2" "github.com/google/shlex" "github.com/moby/moby/api/types/network" - "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client/pkg/versions" "github.com/sirupsen/logrus" "gopkg.in/yaml.v3" ) diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 9846dc3f7f..5450ea05ec 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -20,7 +20,7 @@ import ( cliflags "github.com/docker/cli/cli/flags" "github.com/docker/cli/cli/version" platformsignals "github.com/docker/cli/cmd/docker/internal/signals" - "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client/pkg/versions" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" diff --git a/e2e/container/run_test.go b/e2e/container/run_test.go index af0486fdee..5e469abffe 100644 --- a/e2e/container/run_test.go +++ b/e2e/container/run_test.go @@ -14,7 +14,7 @@ import ( "github.com/creack/pty" "github.com/docker/cli/e2e/internal/fixtures" "github.com/docker/cli/internal/test/environment" - "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client/pkg/versions" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/golden" diff --git a/internal/test/builders/volume.go b/internal/test/builders/volume.go index 82cf3a8e39..ed5bab27bb 100644 --- a/internal/test/builders/volume.go +++ b/internal/test/builders/volume.go @@ -4,8 +4,8 @@ import "github.com/moby/moby/api/types/volume" // Volume creates a volume with default values. // Any number of volume function builder can be passed to augment it. -func Volume(builders ...func(vol *volume.Volume)) *volume.Volume { - vol := &volume.Volume{ +func Volume(builders ...func(vol *volume.Volume)) volume.Volume { + vol := volume.Volume{ Name: "volume", Driver: "local", Mountpoint: "/data/volume", @@ -13,7 +13,7 @@ func Volume(builders ...func(vol *volume.Volume)) *volume.Volume { } for _, builder := range builders { - builder(vol) + builder(&vol) } return vol diff --git a/vendor.mod b/vendor.mod index 0044114ad9..b58c8af645 100644 --- a/vendor.mod +++ b/vendor.mod @@ -28,8 +28,8 @@ require ( github.com/google/uuid v1.6.0 github.com/mattn/go-runewidth v0.0.17 github.com/moby/go-archive v0.1.0 - github.com/moby/moby/api v1.52.0-beta.2.0.20251023134003-dcd668d5796b // master - github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b // master + github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825 // master + github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825 // master github.com/moby/patternmatcher v0.6.0 github.com/moby/swarmkit/v2 v2.1.0 github.com/moby/sys/atomicwriter v0.1.0 diff --git a/vendor.sum b/vendor.sum index 4263434416..826a7e5bb2 100644 --- a/vendor.sum +++ b/vendor.sum @@ -170,10 +170,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= -github.com/moby/moby/api v1.52.0-beta.2.0.20251023134003-dcd668d5796b h1:2y00KCjD3Dt6CFi8Zr7kh0ew32S2784EWbyKAXqQw2Q= -github.com/moby/moby/api v1.52.0-beta.2.0.20251023134003-dcd668d5796b/go.mod h1:/ou52HkRydg4+odrUR3vFsGgjIyHvprrpEQEkweL10s= -github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b h1:+JMltOoDeSwWJv4AMXE9e3dSe1h4LD4+bt6tqNO5h0s= -github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b/go.mod h1:sxVfwGqVgh7n+tdxA4gFToQ/lf+bM7zATnvQjVnsKT4= +github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825 h1:hIQtHzNpFguJCWlgZ4z9L83YjLYpf9uP9+3cSYXP9hg= +github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825/go.mod h1:/ou52HkRydg4+odrUR3vFsGgjIyHvprrpEQEkweL10s= +github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825 h1:7kbhU8foMePfI9vB24bSld1RzJQpbquW8sZarquRHbY= +github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825/go.mod h1:sxVfwGqVgh7n+tdxA4gFToQ/lf+bM7zATnvQjVnsKT4= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/swarmkit/v2 v2.1.0 h1:u+cJ5hSyF3HnzsyI+NtegYxdIPQIuibk7IbpXNxuISM= diff --git a/vendor/github.com/moby/moby/api/types/swarm/task.go b/vendor/github.com/moby/moby/api/types/swarm/task.go index 1dcbc4d6f8..f61190683c 100644 --- a/vendor/github.com/moby/moby/api/types/swarm/task.go +++ b/vendor/github.com/moby/moby/api/types/swarm/task.go @@ -138,6 +138,17 @@ type DiscreteGenericResource struct { type ResourceRequirements struct { Limits *Limit `json:",omitempty"` Reservations *Resources `json:",omitempty"` + + // Amount of swap in bytes - can only be used together with a memory limit + // -1 means unlimited + // a null pointer keeps the default behaviour of granting twice the memory + // amount in swap + SwapBytes *int64 `json:"SwapBytes,omitzero"` + + // Tune container memory swappiness (0 to 100) - if not specified, defaults + // to the container OS's default - generally 60, or the value predefined in + // the image; set to -1 to unset a previously set value + MemorySwappiness *int64 `json:MemorySwappiness,omitzero"` } // Placement represents orchestration parameters. diff --git a/vendor/github.com/moby/moby/client/build_prune.go b/vendor/github.com/moby/moby/client/build_prune.go index ec17b5a6f3..a22e9685e2 100644 --- a/vendor/github.com/moby/moby/client/build_prune.go +++ b/vendor/github.com/moby/moby/client/build_prune.go @@ -8,7 +8,7 @@ import ( "strconv" "github.com/moby/moby/api/types/build" - "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client/pkg/versions" ) // BuildCachePruneOptions hold parameters to prune the build cache. diff --git a/vendor/github.com/moby/moby/client/client.go b/vendor/github.com/moby/moby/client/client.go index 02bfa87471..643dfbdf8f 100644 --- a/vendor/github.com/moby/moby/client/client.go +++ b/vendor/github.com/moby/moby/client/client.go @@ -56,7 +56,7 @@ import ( cerrdefs "github.com/containerd/errdefs" "github.com/docker/go-connections/sockets" - "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client/pkg/versions" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) diff --git a/vendor/github.com/moby/moby/client/client_interfaces.go b/vendor/github.com/moby/moby/client/client_interfaces.go index 67f880f3b4..a038c33c6e 100644 --- a/vendor/github.com/moby/moby/client/client_interfaces.go +++ b/vendor/github.com/moby/moby/client/client_interfaces.go @@ -12,7 +12,6 @@ import ( "github.com/moby/moby/api/types/registry" "github.com/moby/moby/api/types/swarm" "github.com/moby/moby/api/types/system" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // APIClient is an interface that clients that talk with a docker server must implement. @@ -58,10 +57,10 @@ type HijackDialer interface { // ContainerAPIClient defines API client methods for the containers type ContainerAPIClient interface { - ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (HijackedResponse, error) - ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (container.CommitResponse, error) - ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) - ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error) + ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (ContainerAttachResult, error) + ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (ContainerCommitResult, error) + ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) + ContainerDiff(ctx context.Context, container string, options ContainerDiffOptions) (ContainerDiffResult, error) ExecAPIClient ContainerExport(ctx context.Context, container string) (io.ReadCloser, error) ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error) @@ -158,11 +157,11 @@ type PluginAPIClient interface { // ServiceAPIClient defines API client methods for the services type ServiceAPIClient interface { - ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options ServiceCreateOptions) (ServiceCreateResult, error) + ServiceCreate(ctx context.Context, options ServiceCreateOptions) (ServiceCreateResult, error) ServiceInspect(ctx context.Context, serviceID string, options ServiceInspectOptions) (ServiceInspectResult, error) ServiceList(ctx context.Context, options ServiceListOptions) (ServiceListResult, error) ServiceRemove(ctx context.Context, serviceID string, options ServiceRemoveOptions) (ServiceRemoveResult, error) - ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options ServiceUpdateOptions) (ServiceUpdateResult, error) + ServiceUpdate(ctx context.Context, serviceID string, options ServiceUpdateOptions) (ServiceUpdateResult, error) ServiceLogs(ctx context.Context, serviceID string, options ServiceLogsOptions) (ServiceLogsResult, error) TaskLogs(ctx context.Context, taskID string, options TaskLogsOptions) (TaskLogsResult, error) TaskInspect(ctx context.Context, taskID string, options TaskInspectOptions) (TaskInspectResult, error) @@ -177,7 +176,7 @@ type SwarmAPIClient interface { SwarmUnlock(ctx context.Context, options SwarmUnlockOptions) (SwarmUnlockResult, error) SwarmLeave(ctx context.Context, options SwarmLeaveOptions) (SwarmLeaveResult, error) SwarmInspect(ctx context.Context, options SwarmInspectOptions) (SwarmInspectResult, error) - SwarmUpdate(ctx context.Context, version swarm.Version, options SwarmUpdateOptions) (SwarmUpdateResult, error) + SwarmUpdate(ctx context.Context, options SwarmUpdateOptions) (SwarmUpdateResult, error) } // SystemAPIClient defines API client methods for the system diff --git a/vendor/github.com/moby/moby/client/config_inspect.go b/vendor/github.com/moby/moby/client/config_inspect.go index f1aaf68d98..0bf0ff7916 100644 --- a/vendor/github.com/moby/moby/client/config_inspect.go +++ b/vendor/github.com/moby/moby/client/config_inspect.go @@ -2,6 +2,7 @@ package client import ( "context" + "encoding/json" "github.com/moby/moby/api/types/swarm" ) @@ -14,7 +15,7 @@ type ConfigInspectOptions struct { // ConfigInspectResult holds the result from the ConfigInspect method. type ConfigInspectResult struct { Config swarm.Config - Raw []byte + Raw json.RawMessage } // ConfigInspect returns the config information with raw data @@ -24,7 +25,6 @@ func (cli *Client) ConfigInspect(ctx context.Context, id string, options ConfigI return ConfigInspectResult{}, err } resp, err := cli.get(ctx, "/configs/"+id, nil, nil) - defer ensureReaderClosed(resp) if err != nil { return ConfigInspectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/container_attach.go b/vendor/github.com/moby/moby/client/container_attach.go index a4ffb3e64d..fa3a2efcc9 100644 --- a/vendor/github.com/moby/moby/client/container_attach.go +++ b/vendor/github.com/moby/moby/client/container_attach.go @@ -16,6 +16,11 @@ type ContainerAttachOptions struct { Logs bool } +// ContainerAttachResult is the result from attaching to a container. +type ContainerAttachResult struct { + HijackedResponse +} + // ContainerAttach attaches a connection to a container in the server. // It returns a [HijackedResponse] with the hijacked connection // and a reader to get output. It's up to the called to close @@ -44,10 +49,10 @@ type ContainerAttachOptions struct { // [stdcopy.StdType]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#StdType // [Stdout]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stdout // [Stderr]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stderr -func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (HijackedResponse, error) { +func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (ContainerAttachResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return HijackedResponse{}, err + return ContainerAttachResult{}, err } query := url.Values{} @@ -70,7 +75,12 @@ func (cli *Client) ContainerAttach(ctx context.Context, containerID string, opti query.Set("logs", "1") } - return cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{ + hijacked, err := cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{ "Content-Type": {"text/plain"}, }) + if err != nil { + return ContainerAttachResult{}, err + } + + return ContainerAttachResult{HijackedResponse: hijacked}, nil } diff --git a/vendor/github.com/moby/moby/client/container_commit.go b/vendor/github.com/moby/moby/client/container_commit.go index d948fbd41d..79da44a54f 100644 --- a/vendor/github.com/moby/moby/client/container_commit.go +++ b/vendor/github.com/moby/moby/client/container_commit.go @@ -20,22 +20,27 @@ type ContainerCommitOptions struct { Config *container.Config } +// ContainerCommitResult is the result from committing a container. +type ContainerCommitResult struct { + ID string +} + // ContainerCommit applies changes to a container and creates a new tagged image. -func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (container.CommitResponse, error) { +func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (ContainerCommitResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.CommitResponse{}, err + return ContainerCommitResult{}, err } var repository, tag string if options.Reference != "" { ref, err := reference.ParseNormalizedNamed(options.Reference) if err != nil { - return container.CommitResponse{}, err + return ContainerCommitResult{}, err } if _, ok := ref.(reference.Digested); ok { - return container.CommitResponse{}, errors.New("refusing to create a tag with a digest reference") + return ContainerCommitResult{}, errors.New("refusing to create a tag with a digest reference") } ref = reference.TagNameOnly(ref) @@ -62,9 +67,9 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti resp, err := cli.post(ctx, "/commit", query, options.Config, nil) defer ensureReaderClosed(resp) if err != nil { - return response, err + return ContainerCommitResult{}, err } err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerCommitResult{ID: response.ID}, err } diff --git a/vendor/github.com/moby/moby/client/container_create.go b/vendor/github.com/moby/moby/client/container_create.go index 9d72c636ee..d941a37207 100644 --- a/vendor/github.com/moby/moby/client/container_create.go +++ b/vendor/github.com/moby/moby/client/container_create.go @@ -10,49 +10,63 @@ import ( cerrdefs "github.com/containerd/errdefs" "github.com/moby/moby/api/types/container" - "github.com/moby/moby/api/types/network" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // ContainerCreate creates a new container based on the given configuration. // It can be associated with a name, but it's not mandatory. -func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) { - if config == nil { - return container.CreateResponse{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil") +func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) { + cfg := options.Config + + if cfg == nil { + cfg = &container.Config{} + } + + if options.Image != "" { + if cfg.Image != "" { + return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("either Image or config.Image should be set") + } + newCfg := *cfg + newCfg.Image = options.Image + cfg = &newCfg + } + + if cfg.Image == "" { + return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config.Image or Image is required") } var response container.CreateResponse - if hostConfig != nil { - hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd) - hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop) + if options.HostConfig != nil { + options.HostConfig.CapAdd = normalizeCapabilities(options.HostConfig.CapAdd) + options.HostConfig.CapDrop = normalizeCapabilities(options.HostConfig.CapDrop) } query := url.Values{} - if platform != nil { - if p := formatPlatform(*platform); p != "unknown" { + if options.Platform != nil { + if p := formatPlatform(*options.Platform); p != "unknown" { query.Set("platform", p) } } - if containerName != "" { - query.Set("name", containerName) + if options.Name != "" { + query.Set("name", options.Name) } body := container.CreateRequest{ - Config: config, - HostConfig: hostConfig, - NetworkingConfig: networkingConfig, + Config: cfg, + HostConfig: options.HostConfig, + NetworkingConfig: options.NetworkingConfig, } resp, err := cli.post(ctx, "/containers/create", query, body, nil) defer ensureReaderClosed(resp) if err != nil { - return response, err + return ContainerCreateResult{}, err } err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerCreateResult{ID: response.ID, Warnings: response.Warnings}, err } // formatPlatform returns a formatted string representing platform (e.g., "linux/arm/v7"). diff --git a/vendor/github.com/moby/moby/client/container_create_opts.go b/vendor/github.com/moby/moby/client/container_create_opts.go new file mode 100644 index 0000000000..8580e20d3a --- /dev/null +++ b/vendor/github.com/moby/moby/client/container_create_opts.go @@ -0,0 +1,25 @@ +package client + +import ( + "github.com/moby/moby/api/types/container" + "github.com/moby/moby/api/types/network" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +// ContainerCreateOptions holds parameters to create a container. +type ContainerCreateOptions struct { + Config *container.Config + HostConfig *container.HostConfig + NetworkingConfig *network.NetworkingConfig + Platform *ocispec.Platform + Name string + + // Image is a shortcut for Config.Image - only one of Image or Config.Image should be set. + Image string +} + +// ContainerCreateResult is the result from creating a container. +type ContainerCreateResult struct { + ID string + Warnings []string +} diff --git a/vendor/github.com/moby/moby/client/container_diff.go b/vendor/github.com/moby/moby/client/container_diff.go index c87c6e4be9..ec904337e0 100644 --- a/vendor/github.com/moby/moby/client/container_diff.go +++ b/vendor/github.com/moby/moby/client/container_diff.go @@ -9,22 +9,22 @@ import ( ) // ContainerDiff shows differences in a container filesystem since it was started. -func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) { +func (cli *Client) ContainerDiff(ctx context.Context, containerID string, options ContainerDiffOptions) (ContainerDiffResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return nil, err + return ContainerDiffResult{}, err } resp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) defer ensureReaderClosed(resp) if err != nil { - return nil, err + return ContainerDiffResult{}, err } var changes []container.FilesystemChange err = json.NewDecoder(resp.Body).Decode(&changes) if err != nil { - return nil, err + return ContainerDiffResult{}, err } - return changes, err + return ContainerDiffResult{Changes: changes}, err } diff --git a/vendor/github.com/moby/moby/client/container_diff_opts.go b/vendor/github.com/moby/moby/client/container_diff_opts.go new file mode 100644 index 0000000000..5e3c37ab4e --- /dev/null +++ b/vendor/github.com/moby/moby/client/container_diff_opts.go @@ -0,0 +1,13 @@ +package client + +import "github.com/moby/moby/api/types/container" + +// ContainerDiffOptions holds parameters to show differences in a container filesystem. +type ContainerDiffOptions struct { + // Currently no options, but this allows for future extensibility +} + +// ContainerDiffResult is the result from showing differences in a container filesystem. +type ContainerDiffResult struct { + Changes []container.FilesystemChange +} diff --git a/vendor/github.com/moby/moby/client/container_exec.go b/vendor/github.com/moby/moby/client/container_exec.go index 3b23de487d..bda89110a3 100644 --- a/vendor/github.com/moby/moby/client/container_exec.go +++ b/vendor/github.com/moby/moby/client/container_exec.go @@ -26,7 +26,7 @@ type ExecCreateOptions struct { // ExecCreateResult holds the result of creating a container exec. type ExecCreateResult struct { - container.ExecCreateResponse + ID string } // ExecCreate creates a new exec configuration to run an exec process. @@ -58,7 +58,7 @@ func (cli *Client) ExecCreate(ctx context.Context, containerID string, options E var response container.ExecCreateResponse err = json.NewDecoder(resp.Body).Decode(&response) - return ExecCreateResult{ExecCreateResponse: response}, err + return ExecCreateResult{ID: response.ID}, err } type execStartAttachOptions struct { @@ -127,26 +127,21 @@ func (cli *Client) ExecAttach(ctx context.Context, execID string, options ExecAt return ExecAttachResult{HijackedResponse: response}, err } -// ExecInspect holds information returned by exec inspect. -// -// It provides a subset of the information included in [container.ExecInspectResponse]. -// -// TODO(thaJeztah): include all fields of [container.ExecInspectResponse] ? -type ExecInspect struct { - ExecID string `json:"ID"` - ContainerID string `json:"ContainerID"` - Running bool `json:"Running"` - ExitCode int `json:"ExitCode"` - Pid int `json:"Pid"` -} - // ExecInspectOptions holds options for inspecting a container exec. type ExecInspectOptions struct { } // ExecInspectResult holds the result of inspecting a container exec. +// +// It provides a subset of the information included in [container.ExecInspectResponse]. +// +// TODO(thaJeztah): include all fields of [container.ExecInspectResponse] ? type ExecInspectResult struct { - ExecInspect + ID string + ContainerID string + Running bool + ExitCode int + PID int } // ExecInspect returns information about a specific exec process on the docker host. @@ -168,11 +163,11 @@ func (cli *Client) ExecInspect(ctx context.Context, execID string, options ExecI ec = *response.ExitCode } - return ExecInspectResult{ExecInspect: ExecInspect{ - ExecID: response.ID, + return ExecInspectResult{ + ID: response.ID, ContainerID: response.ContainerID, Running: response.Running, ExitCode: ec, - Pid: response.Pid, - }}, nil + PID: response.Pid, + }, nil } diff --git a/vendor/github.com/moby/moby/client/errors.go b/vendor/github.com/moby/moby/client/errors.go index 81a9f4eb14..4980d7cadc 100644 --- a/vendor/github.com/moby/moby/client/errors.go +++ b/vendor/github.com/moby/moby/client/errors.go @@ -8,7 +8,7 @@ import ( cerrdefs "github.com/containerd/errdefs" "github.com/containerd/errdefs/pkg/errhttp" - "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client/pkg/versions" ) // errConnectionFailed implements an error returned when connection failed. diff --git a/vendor/github.com/moby/moby/client/image_import.go b/vendor/github.com/moby/moby/client/image_import.go index ca0fa1d0f6..b8f1ccb500 100644 --- a/vendor/github.com/moby/moby/client/image_import.go +++ b/vendor/github.com/moby/moby/client/image_import.go @@ -42,5 +42,5 @@ func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, re if err != nil { return ImageImportResult{}, err } - return ImageImportResult{body: resp.Body}, nil + return ImageImportResult{rc: resp.Body}, nil } diff --git a/vendor/github.com/moby/moby/client/image_import_opts.go b/vendor/github.com/moby/moby/client/image_import_opts.go index 44ea0e2caa..2ba5b593ec 100644 --- a/vendor/github.com/moby/moby/client/image_import_opts.go +++ b/vendor/github.com/moby/moby/client/image_import_opts.go @@ -20,16 +20,19 @@ type ImageImportOptions struct { // ImageImportResult holds the response body returned by the daemon for image import. type ImageImportResult struct { - body io.ReadCloser + rc io.ReadCloser } func (r ImageImportResult) Read(p []byte) (n int, err error) { - return r.body.Read(p) + if r.rc == nil { + return 0, io.EOF + } + return r.rc.Read(p) } func (r ImageImportResult) Close() error { - if r.body == nil { + if r.rc == nil { return nil } - return r.body.Close() + return r.rc.Close() } diff --git a/vendor/github.com/moby/moby/client/image_list.go b/vendor/github.com/moby/moby/client/image_list.go index 955422c137..6df3c66e17 100644 --- a/vendor/github.com/moby/moby/client/image_list.go +++ b/vendor/github.com/moby/moby/client/image_list.go @@ -6,7 +6,7 @@ import ( "net/url" "github.com/moby/moby/api/types/image" - "github.com/moby/moby/api/types/versions" + "github.com/moby/moby/client/pkg/versions" ) // ImageList returns a list of images in the docker host. diff --git a/vendor/github.com/moby/moby/client/image_remove.go b/vendor/github.com/moby/moby/client/image_remove.go index 17ed75741c..095b4f04c4 100644 --- a/vendor/github.com/moby/moby/client/image_remove.go +++ b/vendor/github.com/moby/moby/client/image_remove.go @@ -35,5 +35,5 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options Imag var dels []image.DeleteResponse err = json.NewDecoder(resp.Body).Decode(&dels) - return ImageRemoveResult{Deleted: dels}, err + return ImageRemoveResult{Items: dels}, err } diff --git a/vendor/github.com/moby/moby/client/image_remove_opts.go b/vendor/github.com/moby/moby/client/image_remove_opts.go index d028f46086..3b5d8a77f7 100644 --- a/vendor/github.com/moby/moby/client/image_remove_opts.go +++ b/vendor/github.com/moby/moby/client/image_remove_opts.go @@ -14,5 +14,5 @@ type ImageRemoveOptions struct { // ImageRemoveResult holds the delete responses returned by the daemon. type ImageRemoveResult struct { - Deleted []image.DeleteResponse + Items []image.DeleteResponse } diff --git a/vendor/github.com/moby/moby/client/network_inspect.go b/vendor/github.com/moby/moby/client/network_inspect.go index 165aa5b465..7757805276 100644 --- a/vendor/github.com/moby/moby/client/network_inspect.go +++ b/vendor/github.com/moby/moby/client/network_inspect.go @@ -2,6 +2,7 @@ package client import ( "context" + "encoding/json" "net/url" "github.com/moby/moby/api/types/network" @@ -10,7 +11,7 @@ import ( // NetworkInspectResult contains the result of a network inspection. type NetworkInspectResult struct { Network network.Inspect - Raw []byte + Raw json.RawMessage } // NetworkInspect returns the information for a specific network configured in the docker host. @@ -28,7 +29,6 @@ func (cli *Client) NetworkInspect(ctx context.Context, networkID string, options } resp, err := cli.get(ctx, "/networks/"+networkID, query, nil) - defer ensureReaderClosed(resp) if err != nil { return NetworkInspectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/node_inspect.go b/vendor/github.com/moby/moby/client/node_inspect.go index b6ba94fb6e..cd4ce0119f 100644 --- a/vendor/github.com/moby/moby/client/node_inspect.go +++ b/vendor/github.com/moby/moby/client/node_inspect.go @@ -9,9 +9,12 @@ import ( "github.com/moby/moby/api/types/swarm" ) +// NodeInspectOptions holds parameters to inspect nodes with. +type NodeInspectOptions struct{} + type NodeInspectResult struct { Node swarm.Node - Raw []byte + Raw json.RawMessage } // NodeInspect returns the node information. diff --git a/vendor/github.com/moby/moby/client/node_list.go b/vendor/github.com/moby/moby/client/node_list.go index 6952d5fe2b..1a1b57922e 100644 --- a/vendor/github.com/moby/moby/client/node_list.go +++ b/vendor/github.com/moby/moby/client/node_list.go @@ -8,6 +8,11 @@ import ( "github.com/moby/moby/api/types/swarm" ) +// NodeListOptions holds parameters to list nodes with. +type NodeListOptions struct { + Filters Filters +} + type NodeListResult struct { Items []swarm.Node } diff --git a/vendor/github.com/moby/moby/client/node_remove.go b/vendor/github.com/moby/moby/client/node_remove.go index c7f6d7ea8a..56c39d67a6 100644 --- a/vendor/github.com/moby/moby/client/node_remove.go +++ b/vendor/github.com/moby/moby/client/node_remove.go @@ -5,6 +5,10 @@ import ( "net/url" ) +// NodeRemoveOptions holds parameters to remove nodes with. +type NodeRemoveOptions struct { + Force bool +} type NodeRemoveResult struct{} // NodeRemove removes a Node. diff --git a/vendor/github.com/moby/moby/client/node_update.go b/vendor/github.com/moby/moby/client/node_update.go index 8f9caa4411..4bc7c3b698 100644 --- a/vendor/github.com/moby/moby/client/node_update.go +++ b/vendor/github.com/moby/moby/client/node_update.go @@ -3,8 +3,16 @@ package client import ( "context" "net/url" + + "github.com/moby/moby/api/types/swarm" ) +// NodeUpdateOptions holds parameters to update nodes with. +type NodeUpdateOptions struct { + Version swarm.Version + Spec swarm.NodeSpec +} + type NodeUpdateResult struct{} // NodeUpdate updates a Node. @@ -16,7 +24,7 @@ func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, options NodeUp query := url.Values{} query.Set("version", options.Version.String()) - resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, options.Node, nil) + resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, options.Spec, nil) defer ensureReaderClosed(resp) return NodeUpdateResult{}, err } diff --git a/vendor/github.com/moby/moby/api/types/versions/compare.go b/vendor/github.com/moby/moby/client/pkg/versions/compare.go similarity index 100% rename from vendor/github.com/moby/moby/api/types/versions/compare.go rename to vendor/github.com/moby/moby/client/pkg/versions/compare.go diff --git a/vendor/github.com/moby/moby/client/plugin_inspect.go b/vendor/github.com/moby/moby/client/plugin_inspect.go index e6853e644d..8caf06a8e0 100644 --- a/vendor/github.com/moby/moby/client/plugin_inspect.go +++ b/vendor/github.com/moby/moby/client/plugin_inspect.go @@ -2,6 +2,7 @@ package client import ( "context" + "encoding/json" "github.com/moby/moby/api/types/plugin" ) @@ -13,8 +14,8 @@ type PluginInspectOptions struct { // PluginInspectResult holds the result from the [Client.PluginInspect] method. type PluginInspectResult struct { - Raw []byte Plugin plugin.Plugin + Raw json.RawMessage } // PluginInspect inspects an existing plugin @@ -24,7 +25,6 @@ func (cli *Client) PluginInspect(ctx context.Context, name string, options Plugi return PluginInspectResult{}, err } resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) - defer ensureReaderClosed(resp) if err != nil { return PluginInspectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/secret_inspect.go b/vendor/github.com/moby/moby/client/secret_inspect.go index 360085215a..fefd4cd23d 100644 --- a/vendor/github.com/moby/moby/client/secret_inspect.go +++ b/vendor/github.com/moby/moby/client/secret_inspect.go @@ -2,6 +2,7 @@ package client import ( "context" + "encoding/json" "github.com/moby/moby/api/types/swarm" ) @@ -14,7 +15,7 @@ type SecretInspectOptions struct { // SecretInspectResult holds the result from the [Client.SecretInspect]. method. type SecretInspectResult struct { Secret swarm.Secret - Raw []byte + Raw json.RawMessage } // SecretInspect returns the secret information with raw data. @@ -24,7 +25,6 @@ func (cli *Client) SecretInspect(ctx context.Context, id string, options SecretI return SecretInspectResult{}, err } resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) - defer ensureReaderClosed(resp) if err != nil { return SecretInspectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/service_create.go b/vendor/github.com/moby/moby/client/service_create.go index 9155d508a4..204d21816c 100644 --- a/vendor/github.com/moby/moby/client/service_create.go +++ b/vendor/github.com/moby/moby/client/service_create.go @@ -16,6 +16,8 @@ import ( // ServiceCreateOptions contains the options to use when creating a service. type ServiceCreateOptions struct { + Spec swarm.ServiceSpec + // EncodedRegistryAuth is the encoded registry authorization credentials to // use when updating the service. // @@ -39,33 +41,33 @@ type ServiceCreateResult struct { } // ServiceCreate creates a new service. -func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options ServiceCreateOptions) (ServiceCreateResult, error) { +func (cli *Client) ServiceCreate(ctx context.Context, options ServiceCreateOptions) (ServiceCreateResult, error) { // Make sure containerSpec is not nil when no runtime is set or the runtime is set to container - if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) { - service.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{} + if options.Spec.TaskTemplate.ContainerSpec == nil && (options.Spec.TaskTemplate.Runtime == "" || options.Spec.TaskTemplate.Runtime == swarm.RuntimeContainer) { + options.Spec.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{} } - if err := validateServiceSpec(service); err != nil { + if err := validateServiceSpec(options.Spec); err != nil { return ServiceCreateResult{}, err } // ensure that the image is tagged var warnings []string switch { - case service.TaskTemplate.ContainerSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" { - service.TaskTemplate.ContainerSpec.Image = taggedImg + case options.Spec.TaskTemplate.ContainerSpec != nil: + if taggedImg := imageWithTagString(options.Spec.TaskTemplate.ContainerSpec.Image); taggedImg != "" { + options.Spec.TaskTemplate.ContainerSpec.Image = taggedImg } if options.QueryRegistry { - resolveWarning := resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) + resolveWarning := resolveContainerSpecImage(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth) warnings = append(warnings, resolveWarning) } - case service.TaskTemplate.PluginSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" { - service.TaskTemplate.PluginSpec.Remote = taggedImg + case options.Spec.TaskTemplate.PluginSpec != nil: + if taggedImg := imageWithTagString(options.Spec.TaskTemplate.PluginSpec.Remote); taggedImg != "" { + options.Spec.TaskTemplate.PluginSpec.Remote = taggedImg } if options.QueryRegistry { - resolveWarning := resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) + resolveWarning := resolvePluginSpecRemote(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth) warnings = append(warnings, resolveWarning) } } @@ -74,7 +76,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, if options.EncodedRegistryAuth != "" { headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth} } - resp, err := cli.post(ctx, "/services/create", nil, service, headers) + resp, err := cli.post(ctx, "/services/create", nil, options.Spec, headers) defer ensureReaderClosed(resp) if err != nil { return ServiceCreateResult{}, err diff --git a/vendor/github.com/moby/moby/client/service_inspect.go b/vendor/github.com/moby/moby/client/service_inspect.go index fabae9fb08..9bda43f861 100644 --- a/vendor/github.com/moby/moby/client/service_inspect.go +++ b/vendor/github.com/moby/moby/client/service_inspect.go @@ -2,6 +2,7 @@ package client import ( "context" + "encoding/json" "fmt" "net/url" @@ -16,7 +17,7 @@ type ServiceInspectOptions struct { // ServiceInspectResult represents the result of a service inspect operation. type ServiceInspectResult struct { Service swarm.Service - Raw []byte + Raw json.RawMessage } // ServiceInspect retrieves detailed information about a specific service by its ID. @@ -29,7 +30,6 @@ func (cli *Client) ServiceInspect(ctx context.Context, serviceID string, options query := url.Values{} query.Set("insertDefaults", fmt.Sprintf("%v", options.InsertDefaults)) resp, err := cli.get(ctx, "/services/"+serviceID, query, nil) - defer ensureReaderClosed(resp) if err != nil { return ServiceInspectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/service_update.go b/vendor/github.com/moby/moby/client/service_update.go index 3910d2bc5f..36061c9d16 100644 --- a/vendor/github.com/moby/moby/client/service_update.go +++ b/vendor/github.com/moby/moby/client/service_update.go @@ -12,6 +12,9 @@ import ( // ServiceUpdateOptions contains the options to be used for updating services. type ServiceUpdateOptions struct { + Version swarm.Version + Spec swarm.ServiceSpec + // EncodedRegistryAuth is the encoded registry authorization credentials to // use when updating the service. // @@ -50,13 +53,13 @@ type ServiceUpdateResult struct { // conflicting writes. It must be the value as set *before* the update. // You can find this value in the [swarm.Service.Meta] field, which can // be found using [Client.ServiceInspectWithRaw]. -func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options ServiceUpdateOptions) (ServiceUpdateResult, error) { +func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, options ServiceUpdateOptions) (ServiceUpdateResult, error) { serviceID, err := trimID("service", serviceID) if err != nil { return ServiceUpdateResult{}, err } - if err := validateServiceSpec(service); err != nil { + if err := validateServiceSpec(options.Spec); err != nil { return ServiceUpdateResult{}, err } @@ -69,25 +72,25 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version query.Set("rollback", options.Rollback) } - query.Set("version", version.String()) + query.Set("version", options.Version.String()) // ensure that the image is tagged var warnings []string switch { - case service.TaskTemplate.ContainerSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" { - service.TaskTemplate.ContainerSpec.Image = taggedImg + case options.Spec.TaskTemplate.ContainerSpec != nil: + if taggedImg := imageWithTagString(options.Spec.TaskTemplate.ContainerSpec.Image); taggedImg != "" { + options.Spec.TaskTemplate.ContainerSpec.Image = taggedImg } if options.QueryRegistry { - resolveWarning := resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) + resolveWarning := resolveContainerSpecImage(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth) warnings = append(warnings, resolveWarning) } - case service.TaskTemplate.PluginSpec != nil: - if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" { - service.TaskTemplate.PluginSpec.Remote = taggedImg + case options.Spec.TaskTemplate.PluginSpec != nil: + if taggedImg := imageWithTagString(options.Spec.TaskTemplate.PluginSpec.Remote); taggedImg != "" { + options.Spec.TaskTemplate.PluginSpec.Remote = taggedImg } if options.QueryRegistry { - resolveWarning := resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth) + resolveWarning := resolvePluginSpecRemote(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth) warnings = append(warnings, resolveWarning) } } @@ -96,7 +99,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version if options.EncodedRegistryAuth != "" { headers.Set(registry.AuthHeader, options.EncodedRegistryAuth) } - resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) + resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, options.Spec, headers) defer ensureReaderClosed(resp) if err != nil { return ServiceUpdateResult{}, err diff --git a/vendor/github.com/moby/moby/client/swarm_node_inspect_opts.go b/vendor/github.com/moby/moby/client/swarm_node_inspect_opts.go deleted file mode 100644 index 5423f5c67c..0000000000 --- a/vendor/github.com/moby/moby/client/swarm_node_inspect_opts.go +++ /dev/null @@ -1,4 +0,0 @@ -package client - -// NodeInspectOptions holds parameters to inspect nodes with. -type NodeInspectOptions struct{} diff --git a/vendor/github.com/moby/moby/client/swarm_node_list_opts.go b/vendor/github.com/moby/moby/client/swarm_node_list_opts.go deleted file mode 100644 index c5293cd174..0000000000 --- a/vendor/github.com/moby/moby/client/swarm_node_list_opts.go +++ /dev/null @@ -1,6 +0,0 @@ -package client - -// NodeListOptions holds parameters to list nodes with. -type NodeListOptions struct { - Filters Filters -} diff --git a/vendor/github.com/moby/moby/client/swarm_node_remove_opts.go b/vendor/github.com/moby/moby/client/swarm_node_remove_opts.go deleted file mode 100644 index 85bc12f812..0000000000 --- a/vendor/github.com/moby/moby/client/swarm_node_remove_opts.go +++ /dev/null @@ -1,6 +0,0 @@ -package client - -// NodeRemoveOptions holds parameters to remove nodes with. -type NodeRemoveOptions struct { - Force bool -} diff --git a/vendor/github.com/moby/moby/client/swarm_node_update_opts.go b/vendor/github.com/moby/moby/client/swarm_node_update_opts.go deleted file mode 100644 index 738b9f871f..0000000000 --- a/vendor/github.com/moby/moby/client/swarm_node_update_opts.go +++ /dev/null @@ -1,9 +0,0 @@ -package client - -import "github.com/moby/moby/api/types/swarm" - -// NodeUpdateOptions holds parameters to update nodes with. -type NodeUpdateOptions struct { - Version swarm.Version - Node swarm.NodeSpec -} diff --git a/vendor/github.com/moby/moby/client/swarm_update.go b/vendor/github.com/moby/moby/client/swarm_update.go index 8f62876a56..81f62b2c02 100644 --- a/vendor/github.com/moby/moby/client/swarm_update.go +++ b/vendor/github.com/moby/moby/client/swarm_update.go @@ -10,7 +10,8 @@ import ( // SwarmUpdateOptions contains options for updating a swarm. type SwarmUpdateOptions struct { - Swarm swarm.Spec + Version swarm.Version + Spec swarm.Spec RotateWorkerToken bool RotateManagerToken bool RotateManagerUnlockKey bool @@ -20,13 +21,13 @@ type SwarmUpdateOptions struct { type SwarmUpdateResult struct{} // SwarmUpdate updates the swarm. -func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, options SwarmUpdateOptions) (SwarmUpdateResult, error) { +func (cli *Client) SwarmUpdate(ctx context.Context, options SwarmUpdateOptions) (SwarmUpdateResult, error) { query := url.Values{} - query.Set("version", version.String()) + query.Set("version", options.Version.String()) query.Set("rotateWorkerToken", strconv.FormatBool(options.RotateWorkerToken)) query.Set("rotateManagerToken", strconv.FormatBool(options.RotateManagerToken)) query.Set("rotateManagerUnlockKey", strconv.FormatBool(options.RotateManagerUnlockKey)) - resp, err := cli.post(ctx, "/swarm/update", query, options.Swarm, nil) + resp, err := cli.post(ctx, "/swarm/update", query, options.Spec, nil) defer ensureReaderClosed(resp) return SwarmUpdateResult{}, err } diff --git a/vendor/github.com/moby/moby/client/task_inspect.go b/vendor/github.com/moby/moby/client/task_inspect.go index 277b00ff49..96edcb09f2 100644 --- a/vendor/github.com/moby/moby/client/task_inspect.go +++ b/vendor/github.com/moby/moby/client/task_inspect.go @@ -2,6 +2,7 @@ package client import ( "context" + "encoding/json" "github.com/moby/moby/api/types/swarm" ) @@ -14,7 +15,7 @@ type TaskInspectOptions struct { // TaskInspectResult contains the result of a task inspection. type TaskInspectResult struct { Task swarm.Task - Raw []byte + Raw json.RawMessage } // TaskInspect returns the task information and its raw representation. @@ -25,7 +26,6 @@ func (cli *Client) TaskInspect(ctx context.Context, taskID string, options TaskI } resp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) - defer ensureReaderClosed(resp) if err != nil { return TaskInspectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/utils.go b/vendor/github.com/moby/moby/client/utils.go index 1da948b6c8..54d0deef19 100644 --- a/vendor/github.com/moby/moby/client/utils.go +++ b/vendor/github.com/moby/moby/client/utils.go @@ -70,11 +70,11 @@ func encodePlatform(platform *ocispec.Platform) (string, error) { return string(p), nil } -func decodeWithRaw[T any](resp *http.Response, out *T) (raw []byte, _ error) { +func decodeWithRaw[T any](resp *http.Response, out *T) (raw json.RawMessage, _ error) { if resp == nil || resp.Body == nil { return nil, errors.New("empty response") } - defer resp.Body.Close() + defer ensureReaderClosed(resp) var buf bytes.Buffer tr := io.TeeReader(resp.Body, &buf) diff --git a/vendor/github.com/moby/moby/client/volume_inspect.go b/vendor/github.com/moby/moby/client/volume_inspect.go index 1fa62bd9ec..cf00236a2a 100644 --- a/vendor/github.com/moby/moby/client/volume_inspect.go +++ b/vendor/github.com/moby/moby/client/volume_inspect.go @@ -2,6 +2,7 @@ package client import ( "context" + "encoding/json" "github.com/moby/moby/api/types/volume" ) @@ -13,8 +14,8 @@ type VolumeInspectOptions struct { // VolumeInspectResult holds the result from the [Client.VolumeInspect] method. type VolumeInspectResult struct { - Raw []byte Volume volume.Volume + Raw json.RawMessage } // VolumeInspect returns the information about a specific volume in the docker host. @@ -25,7 +26,6 @@ func (cli *Client) VolumeInspect(ctx context.Context, volumeID string, options V } resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil) - defer ensureReaderClosed(resp) if err != nil { return VolumeInspectResult{}, err } 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 } diff --git a/vendor/modules.txt b/vendor/modules.txt index b3b3acdb1f..b417a7725f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -168,7 +168,7 @@ github.com/moby/docker-image-spec/specs-go/v1 github.com/moby/go-archive github.com/moby/go-archive/compression github.com/moby/go-archive/tarheader -# github.com/moby/moby/api v1.52.0-beta.2.0.20251023134003-dcd668d5796b +# github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825 ## explicit; go 1.23.0 github.com/moby/moby/api/pkg/authconfig github.com/moby/moby/api/pkg/progress @@ -191,9 +191,8 @@ github.com/moby/moby/api/types/registry github.com/moby/moby/api/types/storage github.com/moby/moby/api/types/swarm github.com/moby/moby/api/types/system -github.com/moby/moby/api/types/versions github.com/moby/moby/api/types/volume -# github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b +# github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825 ## explicit; go 1.23.0 github.com/moby/moby/client github.com/moby/moby/client/internal @@ -201,6 +200,7 @@ github.com/moby/moby/client/internal/timestamp github.com/moby/moby/client/pkg/jsonmessage github.com/moby/moby/client/pkg/security github.com/moby/moby/client/pkg/stringid +github.com/moby/moby/client/pkg/versions # github.com/moby/patternmatcher v0.6.0 ## explicit; go 1.19 github.com/moby/patternmatcher From 4afbd6146b766083ac5ff3bf40eeb1e002b97cda Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 25 Oct 2025 01:36:38 +0200 Subject: [PATCH 2/2] implement some ad-hoc mocks for responses Signed-off-by: Sebastiaan van Stijn --- cli/command/image/client_test.go | 13 +++++++++-- cli/command/image/load_test.go | 28 +++++++++++++++++------- cli/command/image/pull_test.go | 7 +++--- cli/command/image/push_test.go | 4 ++-- cli/command/plugin/client_test.go | 4 ++-- cli/command/trust/inspect_pretty_test.go | 12 ++++++++-- cli/command/trust/sign_test.go | 1 - 7 files changed, 48 insertions(+), 21 deletions(-) diff --git a/cli/command/image/client_test.go b/cli/command/image/client_test.go index 1ca583c9d8..2146d1ae4f 100644 --- a/cli/command/image/client_test.go +++ b/cli/command/image/client_test.go @@ -3,6 +3,7 @@ package image import ( "context" "io" + "net/http" "strings" "time" @@ -28,6 +29,14 @@ type fakeClient struct { imageBuildFunc func(context.Context, io.Reader, client.ImageBuildOptions) (client.ImageBuildResult, error) } +type fakeStreamResult struct { + io.ReadCloser + client.ImagePushResponse // same interface as [client.ImagePullResponse] +} + +func (e fakeStreamResult) Read(p []byte) (int, error) { return e.ReadCloser.Read(p) } +func (e fakeStreamResult) Close() error { return e.ReadCloser.Close() } + func (cli *fakeClient) ImageTag(_ context.Context, options client.ImageTagOptions) (client.ImageTagResult, error) { if cli.imageTagFunc != nil { return cli.imageTagFunc(options) @@ -54,7 +63,7 @@ func (cli *fakeClient) ImagePush(_ context.Context, ref string, options client.I return cli.imagePushFunc(ref, options) } // FIXME(thaJeztah): how to mock this? - return nil, nil + return fakeStreamResult{ReadCloser: http.NoBody}, nil } func (cli *fakeClient) Info(_ context.Context) (system.Info, error) { @@ -69,7 +78,7 @@ func (cli *fakeClient) ImagePull(_ context.Context, ref string, options client.I return cli.imagePullFunc(ref, options) } // FIXME(thaJeztah): how to mock this? - return nil, nil + return fakeStreamResult{ReadCloser: http.NoBody}, nil } func (cli *fakeClient) ImagesPrune(_ context.Context, opts client.ImagePruneOptions) (client.ImagePruneResult, error) { diff --git a/cli/command/image/load_test.go b/cli/command/image/load_test.go index 0140012cf1..91f4273cdd 100644 --- a/cli/command/image/load_test.go +++ b/cli/command/image/load_test.go @@ -4,7 +4,10 @@ import ( "errors" "fmt" "io" + "reflect" + "strings" "testing" + "unsafe" "github.com/docker/cli/internal/test" "github.com/moby/moby/client" @@ -71,8 +74,18 @@ func TestNewLoadCommandInvalidInput(t *testing.T) { assert.ErrorContains(t, err, expectedError) } +func mockImageLoadResult(content string, json bool) client.ImageLoadResult { + out := client.ImageLoadResult{JSON: json} + + // Set unexported field "body" + v := reflect.ValueOf(&out).Elem() + f := v.FieldByName("body") + r := io.NopCloser(strings.NewReader(content)) + reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem().Set(reflect.ValueOf(r)) + return out +} + func TestNewLoadCommandSuccess(t *testing.T) { - t.Skip("FIXME(thaJeztah): how to mock this?") testCases := []struct { name string args []string @@ -84,7 +97,7 @@ func TestNewLoadCommandSuccess(t *testing.T) { imageLoadFunc: func(input io.Reader, options ...client.ImageLoadOption) (client.ImageLoadResult, error) { // FIXME(thaJeztah): how to mock this? // return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil - return client.ImageLoadResult{}, nil + return mockImageLoadResult(`Success`, false), nil }, }, { @@ -92,12 +105,11 @@ func TestNewLoadCommandSuccess(t *testing.T) { args: []string{}, imageLoadFunc: func(input io.Reader, options ...client.ImageLoadOption) (client.ImageLoadResult, error) { // FIXME(thaJeztah): how to mock this? - // return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil // return client.ImageLoadResult{ // Body: io.NopCloser(strings.NewReader(`{"ID": "1"}`)), // JSON: true, // }, nil - return client.ImageLoadResult{JSON: true}, nil + return mockImageLoadResult(`{"ID":"1"}`, true), nil }, }, { @@ -106,7 +118,7 @@ func TestNewLoadCommandSuccess(t *testing.T) { imageLoadFunc: func(input io.Reader, options ...client.ImageLoadOption) (client.ImageLoadResult, error) { // FIXME(thaJeztah): how to mock this? // return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil - return client.ImageLoadResult{}, nil + return mockImageLoadResult(`Success`, false), nil }, }, { @@ -118,7 +130,7 @@ func TestNewLoadCommandSuccess(t *testing.T) { // assert.Check(t, is.Contains(options, client.ImageHistoryWithPlatform(ocispec.Platform{OS: "linux", Architecture: "amd64"}))) // FIXME(thaJeztah): how to mock this? // return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil - return client.ImageLoadResult{}, nil + return mockImageLoadResult(`Success`, false), nil }, }, { @@ -128,7 +140,7 @@ func TestNewLoadCommandSuccess(t *testing.T) { assert.Check(t, len(options) > 0) // can be 1 or two depending on whether a terminal is attached :/ // FIXME(thaJeztah): how to mock this? // return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil - return client.ImageLoadResult{}, nil + return mockImageLoadResult(`Success`, false), nil }, }, { @@ -138,7 +150,7 @@ func TestNewLoadCommandSuccess(t *testing.T) { assert.Check(t, len(options) > 0) // can be 1 or two depending on whether a terminal is attached :/ // FIXME(thaJeztah): how to mock this? // return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil - return client.ImageLoadResult{}, nil + return mockImageLoadResult(`Success`, false), nil }, }, } diff --git a/cli/command/image/pull_test.go b/cli/command/image/pull_test.go index 9949d9ab5d..73e2fc7d4f 100644 --- a/cli/command/image/pull_test.go +++ b/cli/command/image/pull_test.go @@ -1,9 +1,9 @@ package image import ( - "errors" "fmt" "io" + "net/http" "testing" "github.com/docker/cli/internal/test" @@ -49,7 +49,6 @@ func TestNewPullCommandErrors(t *testing.T) { } func TestNewPullCommandSuccess(t *testing.T) { - t.Skip("FIXME(thaJeztah): how to mock this?") testCases := []struct { name string args []string @@ -77,7 +76,7 @@ func TestNewPullCommandSuccess(t *testing.T) { imagePullFunc: func(ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) { assert.Check(t, is.Equal(tc.expectedTag, ref), tc.name) // FIXME(thaJeztah): how to mock this? - return nil, nil + return fakeStreamResult{ReadCloser: http.NoBody}, nil }, }) cmd := newPullCommand(cli) @@ -123,7 +122,7 @@ func TestNewPullCommandWithContentTrustErrors(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ imagePullFunc: func(ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) { // FIXME(thaJeztah): how to mock this? - return nil, errors.New("shouldn't try to pull image") + return fakeStreamResult{ReadCloser: http.NoBody}, nil }, }) cli.SetNotaryClient(tc.notaryFunc) diff --git a/cli/command/image/push_test.go b/cli/command/image/push_test.go index bebc5c07d3..dd38cdc84b 100644 --- a/cli/command/image/push_test.go +++ b/cli/command/image/push_test.go @@ -3,6 +3,7 @@ package image import ( "errors" "io" + "net/http" "testing" "github.com/docker/cli/internal/test" @@ -49,7 +50,6 @@ func TestNewPushCommandErrors(t *testing.T) { } func TestNewPushCommandSuccess(t *testing.T) { - t.Skip("FIXME(thaJeztah): how to mock this?") testCases := []struct { name string args []string @@ -72,7 +72,7 @@ func TestNewPushCommandSuccess(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ imagePushFunc: func(ref string, options client.ImagePushOptions) (client.ImagePushResponse, error) { // FIXME(thaJeztah): how to mock this? - return nil, nil + return fakeStreamResult{ReadCloser: http.NoBody}, nil }, }) cmd := newPushCommand(cli) diff --git a/cli/command/plugin/client_test.go b/cli/command/plugin/client_test.go index 455af0b433..453740e03f 100644 --- a/cli/command/plugin/client_test.go +++ b/cli/command/plugin/client_test.go @@ -3,7 +3,7 @@ package plugin import ( "context" "io" - "strings" + "net/http" "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" @@ -79,5 +79,5 @@ func (c *fakeClient) PluginUpgrade(_ context.Context, name string, options clien return c.pluginUpgradeFunc(name, options) } // FIXME(thaJeztah): how to mock this? - return io.NopCloser(strings.NewReader("")), nil + return http.NoBody, nil } diff --git a/cli/command/trust/inspect_pretty_test.go b/cli/command/trust/inspect_pretty_test.go index be69436d62..8cb79cff90 100644 --- a/cli/command/trust/inspect_pretty_test.go +++ b/cli/command/trust/inspect_pretty_test.go @@ -4,8 +4,8 @@ import ( "bytes" "context" "encoding/hex" - "errors" "io" + "net/http" "testing" "github.com/docker/cli/cli/trust" @@ -27,6 +27,14 @@ type fakeClient struct { client.Client } +type fakeStreamResult struct { + io.ReadCloser + client.ImagePushResponse // same interface as [client.ImagePullResponse] +} + +func (e fakeStreamResult) Read(p []byte) (int, error) { return e.ReadCloser.Read(p) } +func (e fakeStreamResult) Close() error { return e.ReadCloser.Close() } + func (*fakeClient) Info(context.Context) (system.Info, error) { return system.Info{}, nil } @@ -37,7 +45,7 @@ func (*fakeClient) ImageInspect(context.Context, string, ...client.ImageInspectO func (*fakeClient) ImagePush(context.Context, string, client.ImagePushOptions) (client.ImagePushResponse, error) { // FIXME(thaJeztah): how to mock this? - return nil, errors.New("don't handle response") + return fakeStreamResult{ReadCloser: http.NoBody}, nil } func TestTrustInspectPrettyCommandErrors(t *testing.T) { diff --git a/cli/command/trust/sign_test.go b/cli/command/trust/sign_test.go index edc3599555..635dc30f21 100644 --- a/cli/command/trust/sign_test.go +++ b/cli/command/trust/sign_test.go @@ -272,7 +272,6 @@ func TestSignCommandChangeListIsCleanedOnError(t *testing.T) { } func TestSignCommandLocalFlag(t *testing.T) { - t.Skip("FIXME(thaJeztah): how to mock this?") cli := test.NewFakeCli(&fakeClient{}) cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository) cmd := newSignCommand(cli)