From 053aa376ea1d224318d8361c5e3bf6bff612a30c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 28 Oct 2025 21:19:59 +0100 Subject: [PATCH] vendor: github.com/moby/moby/api, moby/moby/client master Signed-off-by: Sebastiaan van Stijn --- cli/command/cli.go | 11 +-- cli/command/cli_test.go | 16 ++-- cli/command/completion/functions.go | 4 +- cli/command/completion/functions_test.go | 12 +-- cli/command/container/attach.go | 10 +-- cli/command/container/attach_test.go | 5 +- cli/command/container/client_test.go | 81 ++++++++++++------- cli/command/container/completion.go | 9 ++- cli/command/container/completion_test.go | 12 +-- cli/command/container/cp.go | 41 ++++++---- cli/command/container/cp_test.go | 20 +++-- cli/command/container/create.go | 9 ++- cli/command/container/create_test.go | 6 +- cli/command/container/export.go | 3 +- cli/command/container/export_test.go | 12 +-- cli/command/container/list.go | 12 +-- cli/command/container/list_test.go | 76 +++++++++-------- cli/command/container/logs.go | 8 +- cli/command/container/logs_test.go | 16 ++-- cli/command/container/rename.go | 29 +++---- cli/command/container/run_test.go | 14 +++- cli/command/container/stats.go | 8 +- cli/command/container/top.go | 11 ++- cli/command/container/unpause.go | 2 +- cli/command/container/update.go | 15 ++-- cli/command/container/utils.go | 8 +- cli/command/container/utils_test.go | 8 +- cli/command/container/wait.go | 10 ++- cli/command/image/client_test.go | 7 +- cli/command/network/client_test.go | 22 ++--- cli/command/network/connect.go | 23 +++--- cli/command/network/connect_test.go | 13 +-- cli/command/network/disconnect.go | 19 ++--- cli/command/network/disconnect_test.go | 7 +- cli/command/network/remove.go | 3 +- cli/command/node/client_test.go | 7 +- cli/command/node/cmd.go | 6 +- cli/command/node/formatter.go | 13 ++- cli/command/node/formatter_test.go | 23 +++--- cli/command/node/inspect_test.go | 22 ++--- cli/command/node/list.go | 5 +- cli/command/node/list_test.go | 30 +++---- cli/command/node/ps_test.go | 11 +-- cli/command/plugin/client_test.go | 5 +- cli/command/registry/login.go | 67 ++++++++++----- cli/command/registry/login_test.go | 23 +++--- cli/command/service/client_test.go | 11 ++- cli/command/service/ps_test.go | 8 +- cli/command/stack/client_test.go | 6 +- cli/command/stack/deploy.go | 5 +- cli/command/stack/remove.go | 2 +- cli/command/swarm/client_test.go | 9 ++- cli/command/swarm/join.go | 4 +- cli/command/swarm/join_token.go | 4 +- cli/command/swarm/unlock.go | 4 +- cli/command/system/client_test.go | 26 +++--- cli/command/system/completion.go | 4 +- cli/command/system/completion_test.go | 14 ++-- cli/command/system/events.go | 18 ++--- cli/command/system/info.go | 4 +- cli/command/system/inspect.go | 4 +- cli/command/trust/inspect_pretty_test.go | 5 +- cli/command/volume/client_test.go | 6 +- cli/command/volume/remove.go | 4 +- cli/command/volume/update.go | 12 ++- vendor.mod | 4 +- vendor.sum | 8 +- .../moby/api/types/network/connect_request.go | 20 +++++ .../api/types/network/disconnect_request.go | 21 +++++ vendor/github.com/moby/moby/client/client.go | 75 ++--------------- .../moby/moby/client/client_interfaces.go | 46 +++++------ .../moby/moby/client/container_copy.go | 60 ++++++++++---- .../moby/moby/client/container_export.go | 46 ++++++++++- .../moby/moby/client/container_list.go | 10 ++- .../moby/moby/client/container_logs.go | 45 +++++++++-- .../moby/moby/client/container_rename.go | 18 ++++- .../moby/moby/client/container_top.go | 23 ++++-- .../moby/moby/client/container_unpause.go | 16 ++-- .../moby/moby/client/container_update.go | 28 ++++++- .../moby/moby/client/container_wait.go | 74 +++++++---------- vendor/github.com/moby/moby/client/errors.go | 8 +- .../moby/moby/client/image_history.go | 2 +- .../moby/moby/client/image_inspect.go | 4 +- .../github.com/moby/moby/client/image_load.go | 2 +- .../github.com/moby/moby/client/image_push.go | 2 +- .../github.com/moby/moby/client/image_save.go | 2 +- vendor/github.com/moby/moby/client/login.go | 27 ++++++- .../moby/moby/client/network_connect.go | 26 ++++-- .../moby/moby/client/network_connect_opts.go | 10 --- .../moby/moby/client/network_disconnect.go | 30 +++++-- .../moby/client/network_disconnect_opts.go | 8 -- .../moby/moby/client/network_remove.go | 20 ++++- vendor/github.com/moby/moby/client/ping.go | 48 ++++++++++- .../moby/moby/client/system_events.go | 13 ++- .../moby/moby/client/system_info.go | 18 +++-- .../moby/moby/client/volume_prune.go | 16 ++-- .../moby/moby/client/volume_remove.go | 16 +++- .../moby/moby/client/volume_update.go | 18 ++++- vendor/modules.txt | 4 +- 99 files changed, 1009 insertions(+), 683 deletions(-) create mode 100644 vendor/github.com/moby/moby/api/types/network/connect_request.go create mode 100644 vendor/github.com/moby/moby/api/types/network/disconnect_request.go delete mode 100644 vendor/github.com/moby/moby/client/network_connect_opts.go delete mode 100644 vendor/github.com/moby/moby/client/network_disconnect_opts.go diff --git a/cli/command/cli.go b/cli/command/cli.go index 3a3569b952..e102e83824 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -377,24 +377,21 @@ func (cli *DockerCli) initializeFromClient() { ctx, cancel := context.WithTimeout(cli.baseCtx, cli.getInitTimeout()) defer cancel() - ping, err := cli.client.Ping(ctx, client.PingOptions{}) + ping, err := cli.client.Ping(ctx, client.PingOptions{ + NegotiateAPIVersion: true, + ForceNegotiate: true, + }) if err != nil { // Default to true if we fail to connect to daemon cli.serverInfo = ServerInfo{HasExperimental: true} - - if ping.APIVersion != "" { - cli.client.NegotiateAPIVersionPing(ping) - } return } - cli.serverInfo = ServerInfo{ HasExperimental: ping.Experimental, OSType: ping.OSType, BuildkitVersion: ping.BuilderVersion, SwarmStatus: ping.SwarmStatus, } - cli.client.NegotiateAPIVersionPing(ping) } // ContextStore returns the ContextStore diff --git a/cli/command/cli_test.go b/cli/command/cli_test.go index 6b7813e841..000b26f1b2 100644 --- a/cli/command/cli_test.go +++ b/cli/command/cli_test.go @@ -139,18 +139,22 @@ type fakeClient struct { negotiated bool } -func (c *fakeClient) Ping(_ context.Context, _ client.PingOptions) (client.PingResult, error) { - return c.pingFunc() +func (c *fakeClient) Ping(_ context.Context, options client.PingOptions) (client.PingResult, error) { + res, err := c.pingFunc() + if options.NegotiateAPIVersion { + if res.APIVersion != "" { + if c.negotiated || options.ForceNegotiate { + c.negotiated = true + } + } + } + return res, err } func (c *fakeClient) ClientVersion() string { return c.version } -func (c *fakeClient) NegotiateAPIVersionPing(client.PingResult) { - c.negotiated = true -} - func TestInitializeFromClient(t *testing.T) { const defaultVersion = "v1.55" diff --git a/cli/command/completion/functions.go b/cli/command/completion/functions.go index d8a5a71d32..f461d5befc 100644 --- a/cli/command/completion/functions.go +++ b/cli/command/completion/functions.go @@ -77,7 +77,7 @@ func ImageNamesWithBase(dockerCLI APIClientProvider, limit int) cobra.Completion // Set DOCKER_COMPLETION_SHOW_CONTAINER_IDS=yes to also complete IDs. func ContainerNames(dockerCLI APIClientProvider, all bool, filters ...func(container.Summary) bool) cobra.CompletionFunc { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - list, err := dockerCLI.Client().ContainerList(cmd.Context(), client.ContainerListOptions{ + res, err := dockerCLI.Client().ContainerList(cmd.Context(), client.ContainerListOptions{ All: all, }) if err != nil { @@ -87,7 +87,7 @@ func ContainerNames(dockerCLI APIClientProvider, all bool, filters ...func(conta showContainerIDs := os.Getenv("DOCKER_COMPLETION_SHOW_CONTAINER_IDS") == "yes" var names []string - for _, ctr := range list { + for _, ctr := range res.Items { skip := false for _, fn := range filters { if fn != nil && !fn(ctr) { diff --git a/cli/command/completion/functions_test.go b/cli/command/completion/functions_test.go index 67803f9a0d..27b52cc16b 100644 --- a/cli/command/completion/functions_test.go +++ b/cli/command/completion/functions_test.go @@ -28,17 +28,17 @@ func (c fakeCLI) Client() client.APIClient { type fakeClient struct { client.Client - containerListFunc func(context.Context, client.ContainerListOptions) ([]container.Summary, error) + containerListFunc func(context.Context, client.ContainerListOptions) (client.ContainerListResult, error) imageListFunc func(context.Context, client.ImageListOptions) (client.ImageListResult, error) networkListFunc func(context.Context, client.NetworkListOptions) (client.NetworkListResult, error) volumeListFunc func(context.Context, client.VolumeListOptions) (client.VolumeListResult, error) } -func (c *fakeClient) ContainerList(ctx context.Context, options client.ContainerListOptions) ([]container.Summary, error) { +func (c *fakeClient) ContainerList(ctx context.Context, options client.ContainerListOptions) (client.ContainerListResult, error) { if c.containerListFunc != nil { return c.containerListFunc(ctx, options) } - return []container.Summary{}, nil + return client.ContainerListResult{}, nil } func (c *fakeClient) ImageList(ctx context.Context, options client.ImageListOptions) (client.ImageListResult, error) { @@ -153,12 +153,12 @@ func TestCompleteContainerNames(t *testing.T) { t.Setenv("DOCKER_COMPLETION_SHOW_CONTAINER_IDS", "yes") } comp := ContainerNames(fakeCLI{&fakeClient{ - containerListFunc: func(_ context.Context, opts client.ContainerListOptions) ([]container.Summary, error) { + containerListFunc: func(_ context.Context, opts client.ContainerListOptions) (client.ContainerListResult, error) { assert.Check(t, is.DeepEqual(opts, tc.expOpts)) if tc.expDirective == cobra.ShellCompDirectiveError { - return nil, errors.New("some error occurred") + return client.ContainerListResult{}, errors.New("some error occurred") } - return tc.containers, nil + return client.ContainerListResult{Items: tc.containers}, nil }, }}, tc.showAll, tc.filters...) diff --git a/cli/command/container/attach.go b/cli/command/container/attach.go index 93bc457b7a..8316c56fb0 100644 --- a/cli/command/container/attach.go +++ b/cli/command/container/attach.go @@ -74,7 +74,7 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o // request channel to wait for client waitCtx := context.WithoutCancel(ctx) - resultC, errC := apiClient.ContainerWait(waitCtx, containerID, "") + waitRes := apiClient.ContainerWait(waitCtx, containerID, client.ContainerWaitOptions{}) c, err := inspectContainerAndCheckState(ctx, apiClient, containerID) if err != nil { @@ -152,19 +152,19 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o return err } - return getExitStatus(errC, resultC) + return getExitStatus(waitRes) } -func getExitStatus(errC <-chan error, resultC <-chan container.WaitResponse) error { +func getExitStatus(waitRes client.ContainerWaitResult) error { select { - case result := <-resultC: + case result := <-waitRes.Result: if result.Error != nil { return errors.New(result.Error.Message) } if result.StatusCode != 0 { return cli.StatusError{StatusCode: int(result.StatusCode)} } - case err := <-errC: + case err := <-waitRes.Error: return err } diff --git a/cli/command/container/attach_test.go b/cli/command/container/attach_test.go index cbb701519c..60b9c51ed1 100644 --- a/cli/command/container/attach_test.go +++ b/cli/command/container/attach_test.go @@ -125,7 +125,10 @@ func TestGetExitStatus(t *testing.T) { resultC <- *testcase.result } - err := getExitStatus(errC, resultC) + err := getExitStatus(client.ContainerWaitResult{ + Result: resultC, + Error: errC, + }) if testcase.expectedError == nil { assert.NilError(t, err) diff --git a/cli/command/container/client_test.go b/cli/command/container/client_test.go index 238e3190ac..3dc0be9720 100644 --- a/cli/command/container/client_test.go +++ b/cli/command/container/client_test.go @@ -3,12 +3,35 @@ package container import ( "context" "io" + "reflect" + "strings" + "unsafe" - "github.com/moby/moby/api/types/container" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) +func mockContainerExportResult(content string) client.ContainerExportResult { + out := client.ContainerExportResult{} + + // Set unexported field "rc" + v := reflect.ValueOf(&out).Elem() + f := v.FieldByName("rc") + r := io.NopCloser(strings.NewReader(content)) + reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem().Set(reflect.ValueOf(r)) + return out +} + +func mockContainerLogsResult(content string) client.ContainerLogsResult { + out := client.ContainerLogsResult{} + + // Set unexported field "rc" + v := reflect.ValueOf(&out).Elem() + f := v.FieldByName("rc") + r := io.NopCloser(strings.NewReader(content)) + reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem().Set(reflect.ValueOf(r)) + return out +} + type fakeClient struct { client.Client inspectFunc func(string) (client.ContainerInspectResult, error) @@ -17,13 +40,13 @@ type fakeClient struct { createContainerFunc func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) containerStartFunc func(containerID string, options client.ContainerStartOptions) (client.ContainerStartResult, error) imageCreateFunc func(ctx context.Context, parentReference string, options client.ImageCreateOptions) (client.ImageCreateResult, error) - infoFunc func() (system.Info, error) - containerStatPathFunc func(containerID, path string) (container.PathStat, error) - containerCopyFromFunc func(containerID, srcPath string) (io.ReadCloser, container.PathStat, error) - logFunc func(string, client.ContainerLogsOptions) (io.ReadCloser, error) - waitFunc func(string) (<-chan container.WaitResponse, <-chan error) - containerListFunc func(client.ContainerListOptions) ([]container.Summary, error) - containerExportFunc func(string) (io.ReadCloser, error) + infoFunc func() (client.SystemInfoResult, error) + containerStatPathFunc func(containerID, path string) (client.ContainerStatPathResult, error) + containerCopyFromFunc func(containerID, srcPath string) (client.CopyFromContainerResult, error) + logFunc func(string, client.ContainerLogsOptions) (client.ContainerLogsResult, error) + waitFunc func(string) client.ContainerWaitResult + containerListFunc func(client.ContainerListOptions) (client.ContainerListResult, error) + containerExportFunc func(string) (client.ContainerExportResult, error) containerExecResizeFunc func(id string, options client.ExecResizeOptions) (client.ExecResizeResult, error) containerRemoveFunc func(ctx context.Context, containerID string, options client.ContainerRemoveOptions) (client.ContainerRemoveResult, error) containerRestartFunc func(ctx context.Context, containerID string, options client.ContainerRestartOptions) (client.ContainerRestartResult, error) @@ -38,14 +61,14 @@ type fakeClient struct { Version string } -func (f *fakeClient) ContainerList(_ context.Context, options client.ContainerListOptions) ([]container.Summary, error) { +func (f *fakeClient) ContainerList(_ context.Context, options client.ContainerListOptions) (client.ContainerListResult, error) { if f.containerListFunc != nil { return f.containerListFunc(options) } - return []container.Summary{}, nil + return client.ContainerListResult{}, nil } -func (f *fakeClient) ContainerInspect(_ context.Context, containerID string, options client.ContainerInspectOptions) (client.ContainerInspectResult, error) { +func (f *fakeClient) ContainerInspect(_ context.Context, containerID string, _ client.ContainerInspectOptions) (client.ContainerInspectResult, error) { if f.inspectFunc != nil { return f.inspectFunc(containerID) } @@ -91,43 +114,43 @@ func (f *fakeClient) ImageCreate(ctx context.Context, parentReference string, op return client.ImageCreateResult{}, nil } -func (f *fakeClient) Info(_ context.Context) (system.Info, error) { +func (f *fakeClient) Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error) { if f.infoFunc != nil { return f.infoFunc() } - return system.Info{}, nil + return client.SystemInfoResult{}, nil } -func (f *fakeClient) ContainerStatPath(_ context.Context, containerID, path string) (container.PathStat, error) { +func (f *fakeClient) ContainerStatPath(_ context.Context, containerID string, options client.ContainerStatPathOptions) (client.ContainerStatPathResult, error) { if f.containerStatPathFunc != nil { - return f.containerStatPathFunc(containerID, path) + return f.containerStatPathFunc(containerID, options.Path) } - return container.PathStat{}, nil + return client.ContainerStatPathResult{}, nil } -func (f *fakeClient) CopyFromContainer(_ context.Context, containerID, srcPath string) (io.ReadCloser, container.PathStat, error) { +func (f *fakeClient) CopyFromContainer(_ context.Context, containerID string, options client.CopyFromContainerOptions) (client.CopyFromContainerResult, error) { if f.containerCopyFromFunc != nil { - return f.containerCopyFromFunc(containerID, srcPath) + return f.containerCopyFromFunc(containerID, options.SourcePath) } - return nil, container.PathStat{}, nil + return client.CopyFromContainerResult{}, nil } -func (f *fakeClient) ContainerLogs(_ context.Context, containerID string, options client.ContainerLogsOptions) (io.ReadCloser, error) { +func (f *fakeClient) ContainerLogs(_ context.Context, containerID string, options client.ContainerLogsOptions) (client.ContainerLogsResult, error) { if f.logFunc != nil { return f.logFunc(containerID, options) } - return nil, nil + return client.ContainerLogsResult{}, nil } func (f *fakeClient) ClientVersion() string { return f.Version } -func (f *fakeClient) ContainerWait(_ context.Context, containerID string, _ container.WaitCondition) (<-chan container.WaitResponse, <-chan error) { +func (f *fakeClient) ContainerWait(_ context.Context, containerID string, _ client.ContainerWaitOptions) client.ContainerWaitResult { if f.waitFunc != nil { return f.waitFunc(containerID) } - return nil, nil + return client.ContainerWaitResult{} } func (f *fakeClient) ContainerStart(_ context.Context, containerID string, options client.ContainerStartOptions) (client.ContainerStartResult, error) { @@ -137,11 +160,11 @@ func (f *fakeClient) ContainerStart(_ context.Context, containerID string, optio return client.ContainerStartResult{}, nil } -func (f *fakeClient) ContainerExport(_ context.Context, containerID string) (io.ReadCloser, error) { +func (f *fakeClient) ContainerExport(_ context.Context, containerID string, _ client.ContainerExportOptions) (client.ContainerExportResult, error) { if f.containerExportFunc != nil { return f.containerExportFunc(containerID) } - return nil, nil + return client.ContainerExportResult{}, nil } func (f *fakeClient) ExecResize(_ context.Context, id string, options client.ExecResizeOptions) (client.ExecResizeResult, error) { @@ -194,12 +217,12 @@ func (f *fakeClient) ContainerDiff(ctx context.Context, containerID string, _ cl return client.ContainerDiffResult{}, nil } -func (f *fakeClient) ContainerRename(ctx context.Context, oldName, newName string) error { +func (f *fakeClient) ContainerRename(ctx context.Context, oldName string, options client.ContainerRenameOptions) (client.ContainerRenameResult, error) { if f.containerRenameFunc != nil { - return f.containerRenameFunc(ctx, oldName, newName) + return client.ContainerRenameResult{}, f.containerRenameFunc(ctx, oldName, options.NewName) } - return nil + return client.ContainerRenameResult{}, nil } func (f *fakeClient) ContainerCommit(ctx context.Context, containerID string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) { diff --git a/cli/command/container/completion.go b/cli/command/container/completion.go index 37d598ceb2..f72a433000 100644 --- a/cli/command/container/completion.go +++ b/cli/command/container/completion.go @@ -9,6 +9,7 @@ import ( "github.com/docker/cli/cli/command/completion" "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/moby/sys/capability" "github.com/moby/sys/signal" "github.com/spf13/cobra" @@ -186,11 +187,11 @@ func completeLink(dockerCLI completion.APIClientProvider) cobra.CompletionFunc { // of the build-in log drivers. func completeLogDriver(dockerCLI completion.APIClientProvider) cobra.CompletionFunc { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - info, err := dockerCLI.Client().Info(cmd.Context()) + res, err := dockerCLI.Client().Info(cmd.Context(), client.InfoOptions{}) if err != nil { return builtInLogDrivers(), cobra.ShellCompDirectiveNoFileComp } - drivers := info.Plugins.Log + drivers := res.Info.Plugins.Log return drivers, cobra.ShellCompDirectiveNoFileComp } } @@ -279,12 +280,12 @@ func completeUlimit(_ *cobra.Command, _ []string, _ string) ([]string, cobra.She // completeVolumeDriver contacts the API to get the built-in and installed volume drivers. func completeVolumeDriver(dockerCLI completion.APIClientProvider) cobra.CompletionFunc { return func(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { - info, err := dockerCLI.Client().Info(cmd.Context()) + res, err := dockerCLI.Client().Info(cmd.Context(), client.InfoOptions{}) if err != nil { // fallback: the built-in drivers return []string{"local"}, cobra.ShellCompDirectiveNoFileComp } - drivers := info.Plugins.Volume + drivers := res.Info.Plugins.Volume return drivers, cobra.ShellCompDirectiveNoFileComp } } diff --git a/cli/command/container/completion_test.go b/cli/command/container/completion_test.go index 2523c52ea0..21b20211d2 100644 --- a/cli/command/container/completion_test.go +++ b/cli/command/container/completion_test.go @@ -27,7 +27,7 @@ func TestCompleteLinuxCapabilityNames(t *testing.T) { func TestCompletePid(t *testing.T) { tests := []struct { - containerListFunc func(client.ContainerListOptions) ([]container.Summary, error) + containerListFunc func(client.ContainerListOptions) (client.ContainerListResult, error) toComplete string expectedCompletions []string expectedDirective cobra.ShellCompDirective @@ -43,10 +43,12 @@ func TestCompletePid(t *testing.T) { expectedDirective: cobra.ShellCompDirectiveNoSpace, }, { - containerListFunc: func(client.ContainerListOptions) ([]container.Summary, error) { - return []container.Summary{ - *builders.Container("c1"), - *builders.Container("c2"), + containerListFunc: func(client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{ + Items: []container.Summary{ + *builders.Container("c1"), + *builders.Container("c2"), + }, }, nil }, toComplete: "container:", diff --git a/cli/command/container/cp.go b/cli/command/container/cp.go index ecd4c7e72b..5121cb88a5 100644 --- a/cli/command/container/cp.go +++ b/cli/command/container/cp.go @@ -230,11 +230,13 @@ func copyFromContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cp // if client requests to follow symbol link, then must decide target file to be copied var rebaseName string if copyConfig.followLink { - srcStat, err := apiClient.ContainerStatPath(ctx, copyConfig.container, srcPath) + src, err := apiClient.ContainerStatPath(ctx, copyConfig.container, client.ContainerStatPathOptions{ + Path: srcPath, + }) // If the destination is a symbolic link, we should follow it. - if err == nil && srcStat.Mode&os.ModeSymlink != 0 { - linkTarget := srcStat.LinkTarget + if err == nil && src.Stat.Mode&os.ModeSymlink != 0 { + linkTarget := src.Stat.LinkTarget if !isAbs(linkTarget) { // Join with the parent directory. srcParent, _ := archive.SplitPathDirEntry(srcPath) @@ -249,11 +251,14 @@ func copyFromContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cp ctx, cancel := signal.NotifyContext(ctx, os.Interrupt) defer cancel() - content, stat, err := apiClient.CopyFromContainer(ctx, copyConfig.container, srcPath) + cpRes, err := apiClient.CopyFromContainer(ctx, copyConfig.container, client.CopyFromContainerOptions{ + SourcePath: srcPath, + }) if err != nil { return err } - defer content.Close() + content := cpRes.Content + defer func() { _ = content.Close() }() if dstPath == "-" { _, err = io.Copy(dockerCLI.Out(), content) @@ -263,7 +268,7 @@ func copyFromContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cp srcInfo := archive.CopyInfo{ Path: srcPath, Exists: true, - IsDir: stat.Mode.IsDir(), + IsDir: cpRes.Stat.Mode.IsDir(), RebaseName: rebaseName, } @@ -315,10 +320,10 @@ func copyToContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cpCo apiClient := dockerCLI.Client() // Prepare destination copy info by stat-ing the container path. dstInfo := archive.CopyInfo{Path: dstPath} - if dstStat, err := apiClient.ContainerStatPath(ctx, copyConfig.container, dstPath); err == nil { + if dst, err := apiClient.ContainerStatPath(ctx, copyConfig.container, client.ContainerStatPathOptions{Path: dstPath}); err == nil { // If the destination is a symbolic link, we should evaluate it. - if dstStat.Mode&os.ModeSymlink != 0 { - linkTarget := dstStat.LinkTarget + if dst.Stat.Mode&os.ModeSymlink != 0 { + linkTarget := dst.Stat.LinkTarget if !isAbs(linkTarget) { // Join with the parent directory. dstParent, _ := archive.SplitPathDirEntry(dstPath) @@ -326,14 +331,14 @@ func copyToContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cpCo } dstInfo.Path = linkTarget - dstStat, err = apiClient.ContainerStatPath(ctx, copyConfig.container, linkTarget) + dst, err = apiClient.ContainerStatPath(ctx, copyConfig.container, client.ContainerStatPathOptions{Path: linkTarget}) } // Validate the destination path if err == nil { - if err := command.ValidateOutputPathFileMode(dstStat.Mode); err != nil { + if err := command.ValidateOutputPathFileMode(dst.Stat.Mode); err != nil { return fmt.Errorf(`destination "%s:%s" must be a directory or a regular file: %w`, copyConfig.container, dstPath, err) } - dstInfo.Exists, dstInfo.IsDir = true, dstStat.Mode.IsDir() + dstInfo.Exists, dstInfo.IsDir = true, dst.Stat.Mode.IsDir() } // Ignore any error and assume that the parent directory of the destination @@ -399,22 +404,26 @@ func copyToContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cpCo } options := client.CopyToContainerOptions{ - CopyUIDGID: copyConfig.copyUIDGID, + DestinationPath: resolvedDstPath, + Content: content, + CopyUIDGID: copyConfig.copyUIDGID, } if copyConfig.quiet { - return apiClient.CopyToContainer(ctx, copyConfig.container, resolvedDstPath, content, options) + _, err := apiClient.CopyToContainer(ctx, copyConfig.container, options) + return err } ctx, cancel := signal.NotifyContext(ctx, os.Interrupt) restore, done := copyProgress(ctx, dockerCLI.Err(), copyToContainerHeader, &copiedSize) - res := apiClient.CopyToContainer(ctx, copyConfig.container, resolvedDstPath, content, options) + // TODO(thaJeztah): error-handling looks odd here; should it be handled differently? + _, err := apiClient.CopyToContainer(ctx, copyConfig.container, options) cancel() <-done restore() _, _ = fmt.Fprintln(dockerCLI.Err(), "Successfully copied", progressHumanSize(copiedSize), "to", copyConfig.container+":"+dstInfo.Path) - return res + return err } // We use `:` as a delimiter between CONTAINER and PATH, but `:` could also be diff --git a/cli/command/container/cp_test.go b/cli/command/container/cp_test.go index 670e7a44a4..cb724f9d98 100644 --- a/cli/command/container/cp_test.go +++ b/cli/command/container/cp_test.go @@ -11,7 +11,7 @@ import ( "github.com/docker/cli/internal/test" "github.com/moby/go-archive" "github.com/moby/go-archive/compression" - "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/fs" @@ -52,9 +52,11 @@ func TestRunCopyFromContainerToStdout(t *testing.T) { tarContent := "the tar content" cli := test.NewFakeCli(&fakeClient{ - containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) { + containerCopyFromFunc: func(ctr, srcPath string) (client.CopyFromContainerResult, error) { assert.Check(t, is.Equal("container", ctr)) - return io.NopCloser(strings.NewReader(tarContent)), container.PathStat{}, nil + return client.CopyFromContainerResult{ + Content: io.NopCloser(strings.NewReader(tarContent)), + }, nil }, }) err := runCopy(context.TODO(), cli, copyOptions{ @@ -73,10 +75,12 @@ func TestRunCopyFromContainerToFilesystem(t *testing.T) { destDir := fs.NewDir(t, "cp-test") cli := test.NewFakeCli(&fakeClient{ - containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) { + containerCopyFromFunc: func(ctr, srcPath string) (client.CopyFromContainerResult, error) { assert.Check(t, is.Equal("container", ctr)) readCloser, err := archive.Tar(srcDir.Path(), compression.None) - return readCloser, container.PathStat{}, err + return client.CopyFromContainerResult{ + Content: readCloser, + }, err }, }) err := runCopy(context.TODO(), cli, copyOptions{ @@ -99,10 +103,12 @@ func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing. defer destDir.Remove() cli := test.NewFakeCli(&fakeClient{ - containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) { + containerCopyFromFunc: func(ctr, srcPath string) (client.CopyFromContainerResult, error) { assert.Check(t, is.Equal("container", ctr)) readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{}) - return readCloser, container.PathStat{}, err + return client.CopyFromContainerResult{ + Content: readCloser, + }, err }, }) err := runCopy(context.TODO(), cli, copyOptions{ diff --git a/cli/command/container/create.go b/cli/command/container/create.go index a645b49989..03b7ac95fa 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -410,7 +410,7 @@ func validatePullOpt(val string) error { // // The path should be an absolute path in the container, commonly // /root/.docker/config.json. -func copyDockerConfigIntoContainer(ctx context.Context, dockerAPI client.APIClient, containerID string, configPath string, config *configfile.ConfigFile) error { +func copyDockerConfigIntoContainer(ctx context.Context, apiClient client.APIClient, containerID string, configPath string, config *configfile.ConfigFile) error { var configBuf bytes.Buffer if err := config.SaveToWriter(&configBuf); err != nil { return fmt.Errorf("saving creds: %w", err) @@ -433,8 +433,11 @@ func copyDockerConfigIntoContainer(ctx context.Context, dockerAPI client.APIClie return fmt.Errorf("closing tar for config copy failed: %w", err) } - if err := dockerAPI.CopyToContainer(ctx, containerID, "/", - &tarBuf, client.CopyToContainerOptions{}); err != nil { + _, err := apiClient.CopyToContainer(ctx, containerID, client.CopyToContainerOptions{ + DestinationPath: "/", + Content: &tarBuf, + }) + if err != nil { return fmt.Errorf("copying config.json into container failed: %w", err) } diff --git a/cli/command/container/create_test.go b/cli/command/container/create_test.go index 234b6bca4f..5a0d7d6654 100644 --- a/cli/command/container/create_test.go +++ b/cli/command/container/create_test.go @@ -128,8 +128,10 @@ func TestCreateContainerImagePullPolicy(t *testing.T) { defer func() { pullCounter++ }() return client.ImageCreateResult{Body: io.NopCloser(strings.NewReader(""))}, nil }, - infoFunc: func() (system.Info, error) { - return system.Info{IndexServerAddress: "https://indexserver.example.com"}, nil + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{ + Info: system.Info{IndexServerAddress: "https://indexserver.example.com"}, + }, nil }, } fakeCLI := test.NewFakeCli(apiClient) diff --git a/cli/command/container/export.go b/cli/command/container/export.go index 1b73e3eae1..0c0f3410b5 100644 --- a/cli/command/container/export.go +++ b/cli/command/container/export.go @@ -9,6 +9,7 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/completion" + "github.com/moby/moby/client" "github.com/moby/sys/atomicwriter" "github.com/spf13/cobra" ) @@ -60,7 +61,7 @@ func runExport(ctx context.Context, dockerCLI command.Cli, opts exportOptions) e output = writer } - responseBody, err := dockerCLI.Client().ContainerExport(ctx, opts.container) + responseBody, err := dockerCLI.Client().ContainerExport(ctx, opts.container, client.ContainerExportOptions{}) if err != nil { return err } diff --git a/cli/command/container/export_test.go b/cli/command/container/export_test.go index 9451eefcb7..8fe6be06b9 100644 --- a/cli/command/container/export_test.go +++ b/cli/command/container/export_test.go @@ -2,10 +2,10 @@ package container import ( "io" - "strings" "testing" "github.com/docker/cli/internal/test" + "github.com/moby/moby/client" "gotest.tools/v3/assert" "gotest.tools/v3/fs" ) @@ -15,8 +15,9 @@ func TestContainerExportOutputToFile(t *testing.T) { defer dir.Remove() cli := test.NewFakeCli(&fakeClient{ - containerExportFunc: func(container string) (io.ReadCloser, error) { - return io.NopCloser(strings.NewReader("bar")), nil + containerExportFunc: func(container string) (client.ContainerExportResult, error) { + // FIXME(thaJeztah): how to mock this? + return mockContainerExportResult("bar"), nil }, }) cmd := newExportCommand(cli) @@ -33,8 +34,9 @@ func TestContainerExportOutputToFile(t *testing.T) { func TestContainerExportOutputToIrregularFile(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerExportFunc: func(container string) (io.ReadCloser, error) { - return io.NopCloser(strings.NewReader("foo")), nil + containerExportFunc: func(container string) (client.ContainerExportResult, error) { + // FIXME(thaJeztah): how to mock this? + return mockContainerExportResult("foo"), nil }, }) cmd := newExportCommand(cli) diff --git a/cli/command/container/list.go b/cli/command/container/list.go index 6decdd3bdf..eb63f6722c 100644 --- a/cli/command/container/list.go +++ b/cli/command/container/list.go @@ -68,8 +68,8 @@ func newListCommand(dockerCLI command.Cli) *cobra.Command { return &cmd } -func buildContainerListOptions(options *psOptions) (*client.ContainerListOptions, error) { - listOptions := &client.ContainerListOptions{ +func buildContainerListOptions(options *psOptions) (client.ContainerListOptions, error) { + listOptions := client.ContainerListOptions{ All: options.all, Limit: options.last, Size: options.size, @@ -84,7 +84,7 @@ func buildContainerListOptions(options *psOptions) (*client.ContainerListOptions if len(options.format) > 0 { tmpl, err := templates.Parse(options.format) if err != nil { - return nil, fmt.Errorf("failed to parse template: %w", err) + return client.ContainerListOptions{}, fmt.Errorf("failed to parse template: %w", err) } optionsProcessor := formatter.NewContainerContext() @@ -92,7 +92,7 @@ func buildContainerListOptions(options *psOptions) (*client.ContainerListOptions // This shouldn't error out but swallowing the error makes it harder // to track down if preProcessor issues come up. if err := tmpl.Execute(io.Discard, optionsProcessor); err != nil { - return nil, fmt.Errorf("failed to execute template: %w", err) + return client.ContainerListOptions{}, fmt.Errorf("failed to execute template: %w", err) } // if `size` was not explicitly set to false (with `--size=false`) @@ -127,7 +127,7 @@ func runPs(ctx context.Context, dockerCLI command.Cli, options *psOptions) error return err } - containers, err := dockerCLI.Client().ContainerList(ctx, *listOptions) + res, err := dockerCLI.Client().ContainerList(ctx, listOptions) if err != nil { return err } @@ -137,5 +137,5 @@ func runPs(ctx context.Context, dockerCLI command.Cli, options *psOptions) error Format: formatter.NewContainerFormat(options.format, options.quiet, listOptions.Size), Trunc: !options.noTrunc, } - return formatter.ContainerWrite(containerCtx, containers) + return formatter.ContainerWrite(containerCtx, res.Items) } diff --git a/cli/command/container/list_test.go b/cli/command/container/list_test.go index c815af85ab..2f49e9721e 100644 --- a/cli/command/container/list_test.go +++ b/cli/command/container/list_test.go @@ -109,7 +109,7 @@ func TestContainerListBuildContainerListOptions(t *testing.T) { func TestContainerListErrors(t *testing.T) { testCases := []struct { flags map[string]string - containerListFunc func(client.ContainerListOptions) ([]container.Summary, error) + containerListFunc func(client.ContainerListOptions) (client.ContainerListResult, error) expectedError string }{ { @@ -125,8 +125,8 @@ func TestContainerListErrors(t *testing.T) { expectedError: `wrong number of args for join`, }, { - containerListFunc: func(_ client.ContainerListOptions) ([]container.Summary, error) { - return nil, errors.New("error listing containers") + containerListFunc: func(_ client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{}, errors.New("error listing containers") }, expectedError: "error listing containers", }, @@ -149,13 +149,15 @@ func TestContainerListErrors(t *testing.T) { func TestContainerListWithoutFormat(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerListFunc: func(_ client.ContainerListOptions) ([]container.Summary, error) { - return []container.Summary{ - *builders.Container("c1"), - *builders.Container("c2", builders.WithName("foo")), - *builders.Container("c3", builders.WithPort(80, 80, builders.TCP), builders.WithPort(81, 81, builders.TCP), builders.WithPort(82, 82, builders.TCP)), - *builders.Container("c4", builders.WithPort(81, 81, builders.UDP)), - *builders.Container("c5", builders.WithPort(82, 82, builders.IP("8.8.8.8"), builders.TCP)), + containerListFunc: func(_ client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{ + Items: []container.Summary{ + *builders.Container("c1"), + *builders.Container("c2", builders.WithName("foo")), + *builders.Container("c3", builders.WithPort(80, 80, builders.TCP), builders.WithPort(81, 81, builders.TCP), builders.WithPort(82, 82, builders.TCP)), + *builders.Container("c4", builders.WithPort(81, 81, builders.UDP)), + *builders.Container("c5", builders.WithPort(82, 82, builders.IP("8.8.8.8"), builders.TCP)), + }, }, nil }, }) @@ -169,10 +171,12 @@ func TestContainerListWithoutFormat(t *testing.T) { func TestContainerListNoTrunc(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerListFunc: func(_ client.ContainerListOptions) ([]container.Summary, error) { - return []container.Summary{ - *builders.Container("c1"), - *builders.Container("c2", builders.WithName("foo/bar")), + containerListFunc: func(_ client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{ + Items: []container.Summary{ + *builders.Container("c1"), + *builders.Container("c2", builders.WithName("foo/bar")), + }, }, nil }, }) @@ -188,10 +192,12 @@ func TestContainerListNoTrunc(t *testing.T) { // Test for GitHub issue docker/docker#21772 func TestContainerListNamesMultipleTime(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerListFunc: func(_ client.ContainerListOptions) ([]container.Summary, error) { - return []container.Summary{ - *builders.Container("c1"), - *builders.Container("c2", builders.WithName("foo/bar")), + containerListFunc: func(_ client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{ + Items: []container.Summary{ + *builders.Container("c1"), + *builders.Container("c2", builders.WithName("foo/bar")), + }, }, nil }, }) @@ -207,10 +213,12 @@ func TestContainerListNamesMultipleTime(t *testing.T) { // Test for GitHub issue docker/docker#30291 func TestContainerListFormatTemplateWithArg(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerListFunc: func(_ client.ContainerListOptions) ([]container.Summary, error) { - return []container.Summary{ - *builders.Container("c1", builders.WithLabel("some.label", "value")), - *builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar")), + containerListFunc: func(_ client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{ + Items: []container.Summary{ + *builders.Container("c1", builders.WithLabel("some.label", "value")), + *builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar")), + }, }, nil }, }) @@ -260,9 +268,9 @@ func TestContainerListFormatSizeSetsOption(t *testing.T) { for _, tc := range tests { t.Run(tc.doc, func(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerListFunc: func(options client.ContainerListOptions) ([]container.Summary, error) { + containerListFunc: func(options client.ContainerListOptions) (client.ContainerListResult, error) { assert.Check(t, is.Equal(options.Size, tc.sizeExpected)) - return []container.Summary{}, nil + return client.ContainerListResult{}, nil }, }) cmd := newListCommand(cli) @@ -280,10 +288,12 @@ func TestContainerListFormatSizeSetsOption(t *testing.T) { func TestContainerListWithConfigFormat(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerListFunc: func(_ client.ContainerListOptions) ([]container.Summary, error) { - return []container.Summary{ - *builders.Container("c1", builders.WithLabel("some.label", "value"), builders.WithSize(10700000)), - *builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar"), builders.WithSize(3200000)), + containerListFunc: func(_ client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{ + Items: []container.Summary{ + *builders.Container("c1", builders.WithLabel("some.label", "value"), builders.WithSize(10700000)), + *builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar"), builders.WithSize(3200000)), + }, }, nil }, }) @@ -300,10 +310,12 @@ func TestContainerListWithConfigFormat(t *testing.T) { func TestContainerListWithFormat(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - containerListFunc: func(_ client.ContainerListOptions) ([]container.Summary, error) { - return []container.Summary{ - *builders.Container("c1", builders.WithLabel("some.label", "value")), - *builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar")), + containerListFunc: func(_ client.ContainerListOptions) (client.ContainerListResult, error) { + return client.ContainerListResult{ + Items: []container.Summary{ + *builders.Container("c1", builders.WithLabel("some.label", "value")), + *builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar")), + }, }, nil }, }) diff --git a/cli/command/container/logs.go b/cli/command/container/logs.go index be84f8e867..ebdbc1f625 100644 --- a/cli/command/container/logs.go +++ b/cli/command/container/logs.go @@ -59,7 +59,7 @@ func runLogs(ctx context.Context, dockerCli command.Cli, opts *logsOptions) erro return err } - responseBody, err := dockerCli.Client().ContainerLogs(ctx, c.Container.ID, client.ContainerLogsOptions{ + resp, err := dockerCli.Client().ContainerLogs(ctx, c.Container.ID, client.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Since: opts.since, @@ -72,12 +72,12 @@ func runLogs(ctx context.Context, dockerCli command.Cli, opts *logsOptions) erro if err != nil { return err } - defer responseBody.Close() + defer func() { _ = resp.Close() }() if c.Container.Config.Tty { - _, err = io.Copy(dockerCli.Out(), responseBody) + _, err = io.Copy(dockerCli.Out(), resp) } else { - _, err = stdcopy.StdCopy(dockerCli.Out(), dockerCli.Err(), responseBody) + _, err = stdcopy.StdCopy(dockerCli.Out(), dockerCli.Err(), resp) } return err } diff --git a/cli/command/container/logs_test.go b/cli/command/container/logs_test.go index e90d983aab..0613092545 100644 --- a/cli/command/container/logs_test.go +++ b/cli/command/container/logs_test.go @@ -2,8 +2,6 @@ package container import ( "context" - "io" - "strings" "testing" "github.com/docker/cli/internal/test" @@ -13,12 +11,6 @@ import ( is "gotest.tools/v3/assert/cmp" ) -var logFn = func(expectedOut string) func(string, client.ContainerLogsOptions) (io.ReadCloser, error) { - return func(container string, opts client.ContainerLogsOptions) (io.ReadCloser, error) { - return io.NopCloser(strings.NewReader(expectedOut)), nil - } -} - func TestRunLogs(t *testing.T) { inspectFn := func(containerID string) (client.ContainerInspectResult, error) { return client.ContainerInspectResult{ @@ -41,7 +33,13 @@ func TestRunLogs(t *testing.T) { doc: "successful logs", expectedOut: "foo", options: &logsOptions{}, - client: &fakeClient{logFunc: logFn("foo"), inspectFunc: inspectFn}, + client: &fakeClient{ + logFunc: func(container string, opts client.ContainerLogsOptions) (client.ContainerLogsResult, error) { + // FIXME(thaJeztah): how to mock this? + return mockContainerLogsResult("foo"), nil + }, + inspectFunc: inspectFn, + }, }, } diff --git a/cli/command/container/rename.go b/cli/command/container/rename.go index a4367c0867..84d6c1a340 100644 --- a/cli/command/container/rename.go +++ b/cli/command/container/rename.go @@ -1,14 +1,13 @@ package container import ( - "context" "errors" "fmt" - "strings" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/completion" + "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -19,7 +18,18 @@ func newRenameCommand(dockerCLI command.Cli) *cobra.Command { Short: "Rename a container", Args: cli.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - return runRename(cmd.Context(), dockerCLI, args[0], args[1]) + oldName, newName := args[0], args[1] + if newName == "" { + // TODO(thaJeztah): remove once https://github.com/moby/moby/pull/51336 is merged and vendored. + return errors.New("new name cannot be blank") + } + _, err := dockerCLI.Client().ContainerRename(cmd.Context(), oldName, client.ContainerRenameOptions{ + NewName: newName, + }) + if err != nil { + return fmt.Errorf("failed to rename container: %w", err) + } + return nil }, Annotations: map[string]string{ "aliases": "docker container rename, docker rename", @@ -29,16 +39,3 @@ func newRenameCommand(dockerCLI command.Cli) *cobra.Command { } return cmd } - -func runRename(ctx context.Context, dockerCLI command.Cli, oldName, newName string) error { - newName = strings.TrimSpace(newName) - if newName == "" { - // TODO(thaJeztah): improve validation in ContainerRename and daemon; the daemon returns an obscure error when providing whitespace-only new-name: - // Error response from daemon: Error when allocating new name: Invalid container name (/ ), only [a-zA-Z0-9][a-zA-Z0-9_.-] are allowed - return errors.New("new name cannot be blank") - } - if err := dockerCLI.Client().ContainerRename(ctx, oldName, newName); err != nil { - return fmt.Errorf("failed to rename container: %w", err) - } - return nil -} diff --git a/cli/command/container/run_test.go b/cli/command/container/run_test.go index a65491bd06..5a8f27c0e4 100644 --- a/cli/command/container/run_test.go +++ b/cli/command/container/run_test.go @@ -89,14 +89,17 @@ func TestRunAttach(t *testing.T) { HijackedResponse: client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), }, nil }, - waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) { + waitFunc: func(_ string) client.ContainerWaitResult { responseChan := make(chan container.WaitResponse, 1) errChan := make(chan error) responseChan <- container.WaitResponse{ StatusCode: 33, } - return responseChan, errChan + return client.ContainerWaitResult{ + Result: responseChan, + Error: errChan, + } }, // use new (non-legacy) wait API // see: https://github.com/docker/cli/commit/38591f20d07795aaef45d400df89ca12f29c603b @@ -166,14 +169,17 @@ func TestRunAttachTermination(t *testing.T) { HijackedResponse: client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), }, nil }, - waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) { + waitFunc: func(_ string) client.ContainerWaitResult { responseChan := make(chan container.WaitResponse, 1) errChan := make(chan error) <-killCh responseChan <- container.WaitResponse{ StatusCode: 130, } - return responseChan, errChan + return client.ContainerWaitResult{ + Result: responseChan, + Error: errChan, + } }, // use new (non-legacy) wait API // see: https://github.com/docker/cli/commit/38591f20d07795aaef45d400df89ca12f29c603b diff --git a/cli/command/container/stats.go b/cli/command/container/stats.go index e6aaa24e0b..39f7e87180 100644 --- a/cli/command/container/stats.go +++ b/cli/command/container/stats.go @@ -183,7 +183,7 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions) // to list containers and to filter events, but the "type" filter // is not valid for filtering containers. f := options.Filters.Clone().Add("type", string(events.ContainerEventType)) - eventChan, errChan := apiClient.Events(ctx, client.EventsListOptions{ + res := apiClient.Events(ctx, client.EventsListOptions{ Filters: f, }) @@ -198,9 +198,9 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions) return case <-ctx.Done(): return - case event := <-eventChan: + case event := <-res.Messages: c <- event - case err := <-errChan: + case err := <-res.Err: // Prevent blocking if closeChan is full or unread select { case closeChan <- err: @@ -229,7 +229,7 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions) if err != nil { return err } - for _, ctr := range cs { + for _, ctr := range cs.Items { if s := NewStats(ctr.ID); cStats.add(s) { waitFirst.Add(1) log.G(ctx).WithFields(map[string]any{ diff --git a/cli/command/container/top.go b/cli/command/container/top.go index 0d61af2f12..6ed7350a49 100644 --- a/cli/command/container/top.go +++ b/cli/command/container/top.go @@ -9,6 +9,7 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/completion" "github.com/docker/cli/cli/command/formatter/tabwriter" + "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -45,17 +46,19 @@ func newTopCommand(dockerCLI command.Cli) *cobra.Command { } func runTop(ctx context.Context, dockerCli command.Cli, opts *topOptions) error { - procList, err := dockerCli.Client().ContainerTop(ctx, opts.container, opts.args) + procList, err := dockerCli.Client().ContainerTop(ctx, opts.container, client.ContainerTopOptions{ + Arguments: opts.args, + }) if err != nil { return err } w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) - fmt.Fprintln(w, strings.Join(procList.Titles, "\t")) + _, _ = fmt.Fprintln(w, strings.Join(procList.Titles, "\t")) for _, proc := range procList.Processes { - fmt.Fprintln(w, strings.Join(proc, "\t")) + _, _ = fmt.Fprintln(w, strings.Join(proc, "\t")) } - w.Flush() + _ = w.Flush() return nil } diff --git a/cli/command/container/unpause.go b/cli/command/container/unpause.go index e18024b994..c4223a87b7 100644 --- a/cli/command/container/unpause.go +++ b/cli/command/container/unpause.go @@ -43,7 +43,7 @@ func newUnpauseCommand(dockerCLI command.Cli) *cobra.Command { func runUnpause(ctx context.Context, dockerCLI command.Cli, opts *unpauseOptions) error { apiClient := dockerCLI.Client() errChan := parallelOperation(ctx, opts.containers, func(ctx context.Context, container string) error { - _, err := apiClient.ContainerUnpause(ctx, container, client.ContainerUnPauseOptions{}) + _, err := apiClient.ContainerUnpause(ctx, container, client.ContainerUnpauseOptions{}) return err }) var errs []error diff --git a/cli/command/container/update.go b/cli/command/container/update.go index 47a35702d7..3bc11412e1 100644 --- a/cli/command/container/update.go +++ b/cli/command/container/update.go @@ -11,6 +11,7 @@ import ( "github.com/docker/cli/cli/command/completion" "github.com/docker/cli/opts" containertypes "github.com/moby/moby/api/types/container" + "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -60,9 +61,9 @@ func newUpdateCommand(dockerCLI command.Cli) *cobra.Command { flags.Int64Var(&options.cpuPeriod, "cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period") flags.Int64Var(&options.cpuQuota, "cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota") flags.Int64Var(&options.cpuRealtimePeriod, "cpu-rt-period", 0, "Limit the CPU real-time period in microseconds") - flags.SetAnnotation("cpu-rt-period", "version", []string{"1.25"}) + _ = flags.SetAnnotation("cpu-rt-period", "version", []string{"1.25"}) flags.Int64Var(&options.cpuRealtimeRuntime, "cpu-rt-runtime", 0, "Limit the CPU real-time runtime in microseconds") - flags.SetAnnotation("cpu-rt-runtime", "version", []string{"1.25"}) + _ = flags.SetAnnotation("cpu-rt-runtime", "version", []string{"1.25"}) flags.StringVar(&options.cpusetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)") flags.StringVar(&options.cpusetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)") flags.Int64VarP(&options.cpuShares, "cpu-shares", "c", 0, "CPU shares (relative weight)") @@ -72,10 +73,10 @@ func newUpdateCommand(dockerCLI command.Cli) *cobra.Command { flags.StringVar(&options.restartPolicy, "restart", "", "Restart policy to apply when a container exits") flags.Int64Var(&options.pidsLimit, "pids-limit", 0, `Tune container pids limit (set -1 for unlimited)`) - flags.SetAnnotation("pids-limit", "version", []string{"1.40"}) + _ = flags.SetAnnotation("pids-limit", "version", []string{"1.40"}) flags.Var(&options.cpus, "cpus", "Number of CPUs") - flags.SetAnnotation("cpus", "version", []string{"1.29"}) + _ = flags.SetAnnotation("cpus", "version", []string{"1.29"}) _ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies) @@ -107,8 +108,8 @@ func runUpdate(ctx context.Context, dockerCli command.Cli, options *updateOption pidsLimit = &options.pidsLimit } - updateConfig := containertypes.UpdateConfig{ - Resources: containertypes.Resources{ + updateConfig := client.ContainerUpdateOptions{ + Resources: &containertypes.Resources{ BlkioWeight: options.blkioWeight, CpusetCpus: options.cpusetCpus, CpusetMems: options.cpusetMems, @@ -123,7 +124,7 @@ func runUpdate(ctx context.Context, dockerCli command.Cli, options *updateOption NanoCPUs: options.cpus.Value(), PidsLimit: pidsLimit, }, - RestartPolicy: restartPolicy, + RestartPolicy: &restartPolicy, } var ( diff --git a/cli/command/container/utils.go b/cli/command/container/utils.go index 363f710f52..7943500e5c 100644 --- a/cli/command/container/utils.go +++ b/cli/command/container/utils.go @@ -20,7 +20,9 @@ func waitExitOrRemoved(ctx context.Context, apiClient client.APIClient, containe condition = container.WaitConditionRemoved } - resultC, errC := apiClient.ContainerWait(ctx, containerID, condition) + waitRes := apiClient.ContainerWait(ctx, containerID, client.ContainerWaitOptions{ + Condition: condition, + }) statusC := make(chan int) go func() { @@ -28,14 +30,14 @@ func waitExitOrRemoved(ctx context.Context, apiClient client.APIClient, containe select { case <-ctx.Done(): return - case result := <-resultC: + case result := <-waitRes.Result: if result.Error != nil { logrus.Errorf("Error waiting for container: %v", result.Error.Message) statusC <- 125 } else { statusC <- int(result.StatusCode) } - case err := <-errC: + case err := <-waitRes.Error: if errors.Is(err, context.Canceled) { return } diff --git a/cli/command/container/utils_test.go b/cli/command/container/utils_test.go index ecdce45eb4..6101f564dc 100644 --- a/cli/command/container/utils_test.go +++ b/cli/command/container/utils_test.go @@ -12,7 +12,7 @@ import ( is "gotest.tools/v3/assert/cmp" ) -func waitFn(cid string) (<-chan container.WaitResponse, <-chan error) { +func waitFn(cid string) client.ContainerWaitResult { resC := make(chan container.WaitResponse) errC := make(chan error, 1) var res container.WaitResponse @@ -33,8 +33,10 @@ func waitFn(cid string) (<-chan container.WaitResponse, <-chan error) { resC <- res } }() - - return resC, errC + return client.ContainerWaitResult{ + Result: resC, + Error: errC, + } } func TestWaitExitOrRemoved(t *testing.T) { diff --git a/cli/command/container/wait.go b/cli/command/container/wait.go index afa4633982..3aabf25e2d 100644 --- a/cli/command/container/wait.go +++ b/cli/command/container/wait.go @@ -4,10 +4,12 @@ import ( "context" "errors" "fmt" + "strconv" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/completion" + "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -42,12 +44,12 @@ func runWait(ctx context.Context, dockerCLI command.Cli, opts *waitOptions) erro var errs []error for _, ctr := range opts.containers { - resultC, errC := apiClient.ContainerWait(ctx, ctr, "") + res := apiClient.ContainerWait(ctx, ctr, client.ContainerWaitOptions{}) select { - case result := <-resultC: - _, _ = fmt.Fprintf(dockerCLI.Out(), "%d\n", result.StatusCode) - case err := <-errC: + case result := <-res.Result: + _, _ = fmt.Fprintln(dockerCLI.Out(), strconv.FormatInt(result.StatusCode, 10)) + case err := <-res.Error: errs = append(errs, err) } } diff --git a/cli/command/image/client_test.go b/cli/command/image/client_test.go index 2146d1ae4f..2f0e52ef94 100644 --- a/cli/command/image/client_test.go +++ b/cli/command/image/client_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/moby/moby/api/types/image" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) @@ -18,7 +17,7 @@ type fakeClient struct { imageSaveFunc func(images []string, options ...client.ImageSaveOption) (client.ImageSaveResult, error) imageRemoveFunc func(image string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error) imagePushFunc func(ref string, options client.ImagePushOptions) (client.ImagePushResponse, error) - infoFunc func() (system.Info, error) + infoFunc func() (client.SystemInfoResult, error) imagePullFunc func(ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) imagesPruneFunc func(options client.ImagePruneOptions) (client.ImagePruneResult, error) imageLoadFunc func(input io.Reader, options ...client.ImageLoadOption) (client.ImageLoadResult, error) @@ -66,11 +65,11 @@ func (cli *fakeClient) ImagePush(_ context.Context, ref string, options client.I return fakeStreamResult{ReadCloser: http.NoBody}, nil } -func (cli *fakeClient) Info(_ context.Context) (system.Info, error) { +func (cli *fakeClient) Info(_ context.Context, _ client.InfoOptions) (client.SystemInfoResult, error) { if cli.infoFunc != nil { return cli.infoFunc() } - return system.Info{}, nil + return client.SystemInfoResult{}, nil } func (cli *fakeClient) ImagePull(_ context.Context, ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) { diff --git a/cli/command/network/client_test.go b/cli/command/network/client_test.go index 527a4c1dc0..0834adfffe 100644 --- a/cli/command/network/client_test.go +++ b/cli/command/network/client_test.go @@ -10,8 +10,8 @@ import ( type fakeClient struct { client.Client networkCreateFunc func(ctx context.Context, name string, options client.NetworkCreateOptions) (network.CreateResponse, error) - networkConnectFunc func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error - networkDisconnectFunc func(ctx context.Context, networkID, container string, force bool) error + networkConnectFunc func(ctx context.Context, networkID string, options client.NetworkConnectOptions) (client.NetworkConnectResult, error) + networkDisconnectFunc func(ctx context.Context, networkID string, options client.NetworkDisconnectOptions) (client.NetworkDisconnectResult, error) networkRemoveFunc func(ctx context.Context, networkID string) error networkListFunc func(ctx context.Context, options client.NetworkListOptions) (client.NetworkListResult, error) networkPruneFunc func(ctx context.Context, options client.NetworkPruneOptions) (client.NetworkPruneResult, error) @@ -25,18 +25,18 @@ func (c *fakeClient) NetworkCreate(ctx context.Context, name string, options cli return network.CreateResponse{}, nil } -func (c *fakeClient) NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error { +func (c *fakeClient) NetworkConnect(ctx context.Context, networkID string, options client.NetworkConnectOptions) (client.NetworkConnectResult, error) { if c.networkConnectFunc != nil { - return c.networkConnectFunc(ctx, networkID, container, config) + return c.networkConnectFunc(ctx, networkID, options) } - return nil + return client.NetworkConnectResult{}, nil } -func (c *fakeClient) NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error { +func (c *fakeClient) NetworkDisconnect(ctx context.Context, networkID string, options client.NetworkDisconnectOptions) (client.NetworkDisconnectResult, error) { if c.networkDisconnectFunc != nil { - return c.networkDisconnectFunc(ctx, networkID, container, force) + return c.networkDisconnectFunc(ctx, networkID, options) } - return nil + return client.NetworkDisconnectResult{}, nil } func (c *fakeClient) NetworkList(ctx context.Context, options client.NetworkListOptions) (client.NetworkListResult, error) { @@ -46,11 +46,11 @@ func (c *fakeClient) NetworkList(ctx context.Context, options client.NetworkList return client.NetworkListResult{}, nil } -func (c *fakeClient) NetworkRemove(ctx context.Context, networkID string) error { +func (c *fakeClient) NetworkRemove(ctx context.Context, networkID string, _ client.NetworkRemoveOptions) (client.NetworkRemoveResult, error) { if c.networkRemoveFunc != nil { - return c.networkRemoveFunc(ctx, networkID) + return client.NetworkRemoveResult{}, c.networkRemoveFunc(ctx, networkID) } - return nil + return client.NetworkRemoveResult{}, nil } func (c *fakeClient) NetworkInspect(ctx context.Context, networkID string, opts client.NetworkInspectOptions) (client.NetworkInspectResult, error) { diff --git a/cli/command/network/connect.go b/cli/command/network/connect.go index 7f2be36ccf..a629005f78 100644 --- a/cli/command/network/connect.go +++ b/cli/command/network/connect.go @@ -68,18 +68,21 @@ func runConnect(ctx context.Context, apiClient client.NetworkAPIClient, options if err != nil { return err } - - return apiClient.NetworkConnect(ctx, options.network, options.container, &network.EndpointSettings{ - IPAMConfig: &network.EndpointIPAMConfig{ - IPv4Address: toNetipAddr(options.ipaddress), - IPv6Address: toNetipAddr(options.ipv6address), - LinkLocalIPs: toNetipAddrSlice(options.linklocalips), + _, err = apiClient.NetworkConnect(ctx, options.network, client.NetworkConnectOptions{ + Container: options.container, + EndpointConfig: &network.EndpointSettings{ + IPAMConfig: &network.EndpointIPAMConfig{ + IPv4Address: toNetipAddr(options.ipaddress), + IPv6Address: toNetipAddr(options.ipv6address), + LinkLocalIPs: toNetipAddrSlice(options.linklocalips), + }, + Links: options.links.GetSlice(), + Aliases: options.aliases, + DriverOpts: driverOpts, + GwPriority: options.gwPriority, }, - Links: options.links.GetSlice(), - Aliases: options.aliases, - DriverOpts: driverOpts, - GwPriority: options.gwPriority, }) + return err } func convertDriverOpt(options []string) (map[string]string, error) { diff --git a/cli/command/network/connect_test.go b/cli/command/network/connect_test.go index e44bb82143..52ede09412 100644 --- a/cli/command/network/connect_test.go +++ b/cli/command/network/connect_test.go @@ -10,6 +10,7 @@ import ( "github.com/docker/cli/internal/test" "github.com/google/go-cmp/cmp/cmpopts" "github.com/moby/moby/api/types/network" + "github.com/moby/moby/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -17,7 +18,7 @@ import ( func TestNetworkConnectErrors(t *testing.T) { testCases := []struct { args []string - networkConnectFunc func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error + networkConnectFunc func(ctx context.Context, networkID string, options client.NetworkConnectOptions) (client.NetworkConnectResult, error) expectedError string }{ { @@ -25,8 +26,8 @@ func TestNetworkConnectErrors(t *testing.T) { }, { args: []string{"toto", "titi"}, - networkConnectFunc: func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error { - return errors.New("error connecting network") + networkConnectFunc: func(ctx context.Context, networkID string, options client.NetworkConnectOptions) (client.NetworkConnectResult, error) { + return client.NetworkConnectResult{}, errors.New("error connecting network") }, expectedError: "error connecting network", }, @@ -61,9 +62,9 @@ func TestNetworkConnectWithFlags(t *testing.T) { GwPriority: 100, } cli := test.NewFakeCli(&fakeClient{ - networkConnectFunc: func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error { - assert.Check(t, is.DeepEqual(expectedConfig, config, cmpopts.EquateComparable(netip.Addr{}))) - return nil + networkConnectFunc: func(ctx context.Context, networkID string, options client.NetworkConnectOptions) (client.NetworkConnectResult, error) { + assert.Check(t, is.DeepEqual(expectedConfig, options.EndpointConfig, cmpopts.EquateComparable(netip.Addr{}))) + return client.NetworkConnectResult{}, nil }, }) args := []string{"mynet", "myctr"} diff --git a/cli/command/network/disconnect.go b/cli/command/network/disconnect.go index df317e4f7d..f868df06f2 100644 --- a/cli/command/network/disconnect.go +++ b/cli/command/network/disconnect.go @@ -1,8 +1,6 @@ package network import ( - "context" - "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/completion" @@ -12,9 +10,7 @@ import ( ) type disconnectOptions struct { - network string - container string - force bool + force bool } func newDisconnectCommand(dockerCLI command.Cli) *cobra.Command { @@ -25,9 +21,12 @@ func newDisconnectCommand(dockerCLI command.Cli) *cobra.Command { Short: "Disconnect a container from a network", Args: cli.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - opts.network = args[0] - opts.container = args[1] - return runDisconnect(cmd.Context(), dockerCLI.Client(), opts) + network := args[0] + _, err := dockerCLI.Client().NetworkDisconnect(cmd.Context(), network, client.NetworkDisconnectOptions{ + Container: args[1], + Force: opts.force, + }) + return err }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { @@ -45,10 +44,6 @@ func newDisconnectCommand(dockerCLI command.Cli) *cobra.Command { return cmd } -func runDisconnect(ctx context.Context, apiClient client.NetworkAPIClient, opts disconnectOptions) error { - return apiClient.NetworkDisconnect(ctx, opts.network, opts.container, opts.force) -} - func isConnected(network string) func(container.Summary) bool { return func(ctr container.Summary) bool { if ctr.NetworkSettings == nil { diff --git a/cli/command/network/disconnect_test.go b/cli/command/network/disconnect_test.go index c9aeea4ec7..d35d293f1c 100644 --- a/cli/command/network/disconnect_test.go +++ b/cli/command/network/disconnect_test.go @@ -7,13 +7,14 @@ import ( "testing" "github.com/docker/cli/internal/test" + "github.com/moby/moby/client" "gotest.tools/v3/assert" ) func TestNetworkDisconnectErrors(t *testing.T) { testCases := []struct { args []string - networkDisconnectFunc func(ctx context.Context, networkID, container string, force bool) error + networkDisconnectFunc func(ctx context.Context, networkID string, options client.NetworkDisconnectOptions) (client.NetworkDisconnectResult, error) expectedError string }{ { @@ -21,8 +22,8 @@ func TestNetworkDisconnectErrors(t *testing.T) { }, { args: []string{"toto", "titi"}, - networkDisconnectFunc: func(ctx context.Context, networkID, container string, force bool) error { - return errors.New("error disconnecting network") + networkDisconnectFunc: func(ctx context.Context, networkID string, options client.NetworkDisconnectOptions) (client.NetworkDisconnectResult, error) { + return client.NetworkDisconnectResult{}, errors.New("error disconnecting network") }, expectedError: "error disconnecting network", }, diff --git a/cli/command/network/remove.go b/cli/command/network/remove.go index 829bab6ecf..314039a6b3 100644 --- a/cli/command/network/remove.go +++ b/cli/command/network/remove.go @@ -59,7 +59,8 @@ func runRemove(ctx context.Context, dockerCLI command.Cli, networks []string, op continue } } - if err := apiClient.NetworkRemove(ctx, name); err != nil { + _, err = apiClient.NetworkRemove(ctx, name, client.NetworkRemoveOptions{}) + if err != nil { if opts.force && errdefs.IsNotFound(err) { continue } diff --git a/cli/command/node/client_test.go b/cli/command/node/client_test.go index f19e499cc1..2e55394b6b 100644 --- a/cli/command/node/client_test.go +++ b/cli/command/node/client_test.go @@ -3,13 +3,12 @@ package node import ( "context" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) type fakeClient struct { client.Client - infoFunc func() (system.Info, error) + infoFunc func() (client.SystemInfoResult, error) nodeInspectFunc func() (client.NodeInspectResult, error) nodeListFunc func() (client.NodeListResult, error) nodeRemoveFunc func() (client.NodeRemoveResult, error) @@ -47,11 +46,11 @@ func (cli *fakeClient) NodeUpdate(_ context.Context, nodeID string, options clie return client.NodeUpdateResult{}, nil } -func (cli *fakeClient) Info(context.Context) (system.Info, error) { +func (cli *fakeClient) Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error) { if cli.infoFunc != nil { return cli.infoFunc() } - return system.Info{}, nil + return client.SystemInfoResult{}, nil } func (cli *fakeClient) TaskInspect(_ context.Context, taskID string, _ client.TaskInspectOptions) (client.TaskInspectResult, error) { diff --git a/cli/command/node/cmd.go b/cli/command/node/cmd.go index e428b4659a..c86cce7632 100644 --- a/cli/command/node/cmd.go +++ b/cli/command/node/cmd.go @@ -45,11 +45,11 @@ func newNodeCommand(dockerCLI command.Cli) *cobra.Command { // the `/info` endpoint. func Reference(ctx context.Context, apiClient client.APIClient, ref string) (string, error) { if ref == "self" { - info, err := apiClient.Info(ctx) + res, err := apiClient.Info(ctx, client.InfoOptions{}) if err != nil { return "", err } - if info.Swarm.NodeID == "" { + if res.Info.Swarm.NodeID == "" { // If there's no node ID in /info, the node probably // isn't a manager. Call a swarm-specific endpoint to // get a more specific error message. @@ -61,7 +61,7 @@ func Reference(ctx context.Context, apiClient client.APIClient, ref string) (str } return "", errors.New("node ID not found in /info") } - return info.Swarm.NodeID, nil + return res.Info.Swarm.NodeID, nil } return ref, nil } diff --git a/cli/command/node/formatter.go b/cli/command/node/formatter.go index 5390e5bccd..68f5d2a9e9 100644 --- a/cli/command/node/formatter.go +++ b/cli/command/node/formatter.go @@ -10,7 +10,6 @@ import ( "github.com/docker/cli/cli/command/inspect" "github.com/docker/go-units" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) @@ -100,7 +99,7 @@ func newFormat(source string, quiet bool) formatter.Format { } // formatWrite writes the context. -func formatWrite(fmtCtx formatter.Context, nodes client.NodeListResult, info system.Info) error { +func formatWrite(fmtCtx formatter.Context, nodes client.NodeListResult, info client.SystemInfoResult) error { nodeCtx := &nodeContext{ HeaderContext: formatter.HeaderContext{ Header: formatter.SubHeaderContext{ @@ -119,7 +118,7 @@ func formatWrite(fmtCtx formatter.Context, nodes client.NodeListResult, info sys for _, node := range nodes.Items { if err := format(&nodeContext{ n: node, - info: info, + info: info.Info.Swarm, }); err != nil { return err } @@ -131,7 +130,7 @@ func formatWrite(fmtCtx formatter.Context, nodes client.NodeListResult, info sys type nodeContext struct { formatter.HeaderContext n swarm.Node - info system.Info + info swarm.Info } func (c *nodeContext) MarshalJSON() ([]byte, error) { @@ -143,7 +142,7 @@ func (c *nodeContext) ID() string { } func (c *nodeContext) Self() bool { - return c.n.ID == c.info.Swarm.NodeID + return c.n.ID == c.info.NodeID } func (c *nodeContext) Hostname() string { @@ -171,10 +170,10 @@ func (c *nodeContext) ManagerStatus() string { } func (c *nodeContext) TLSStatus() string { - if c.info.Swarm.Cluster == nil || reflect.DeepEqual(c.info.Swarm.Cluster.TLSInfo, swarm.TLSInfo{}) || reflect.DeepEqual(c.n.Description.TLSInfo, swarm.TLSInfo{}) { + if c.info.Cluster == nil || reflect.DeepEqual(c.info.Cluster.TLSInfo, swarm.TLSInfo{}) || reflect.DeepEqual(c.n.Description.TLSInfo, swarm.TLSInfo{}) { return "Unknown" } - if reflect.DeepEqual(c.n.Description.TLSInfo, c.info.Swarm.Cluster.TLSInfo) { + if reflect.DeepEqual(c.n.Description.TLSInfo, c.info.Cluster.TLSInfo) { return "Ready" } return "Needs Rotation" diff --git a/cli/command/node/formatter_test.go b/cli/command/node/formatter_test.go index beb937931e..4f233c1d3b 100644 --- a/cli/command/node/formatter_test.go +++ b/cli/command/node/formatter_test.go @@ -208,7 +208,11 @@ foobar_boo Unknown var out bytes.Buffer tc.context.Output = &out - err := formatWrite(tc.context, nodes, system.Info{Swarm: swarm.Info{Cluster: &tc.clusterInfo}}) + err := formatWrite(tc.context, nodes, client.SystemInfoResult{ + Info: system.Info{ + Swarm: swarm.Info{Cluster: &tc.clusterInfo}, + }, + }) if err != nil { assert.Error(t, err, tc.expected) } else { @@ -221,7 +225,7 @@ foobar_boo Unknown func TestNodeContextWriteJSON(t *testing.T) { cases := []struct { expected []map[string]any - info system.Info + info client.SystemInfoResult }{ { expected: []map[string]any{ @@ -229,7 +233,6 @@ func TestNodeContextWriteJSON(t *testing.T) { {"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown", "EngineVersion": ""}, {"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown", "EngineVersion": "18.03.0-ce"}, }, - info: system.Info{}, }, { expected: []map[string]any{ @@ -237,11 +240,13 @@ func TestNodeContextWriteJSON(t *testing.T) { {"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Needs Rotation", "EngineVersion": ""}, {"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown", "EngineVersion": "18.03.0-ce"}, }, - info: system.Info{ - Swarm: swarm.Info{ - Cluster: &swarm.ClusterInfo{ - TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}, - RootRotationInProgress: true, + info: client.SystemInfoResult{ + Info: system.Info{ + Swarm: swarm.Info{ + Cluster: &swarm.ClusterInfo{ + TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}, + RootRotationInProgress: true, + }, }, }, }, @@ -279,7 +284,7 @@ func TestNodeContextWriteJSONField(t *testing.T) { }, } out := bytes.NewBufferString("") - err := formatWrite(formatter.Context{Format: "{{json .ID}}", Output: out}, nodes, system.Info{}) + err := formatWrite(formatter.Context{Format: "{{json .ID}}", Output: out}, nodes, client.SystemInfoResult{}) if err != nil { t.Fatal(err) } diff --git a/cli/command/node/inspect_test.go b/cli/command/node/inspect_test.go index 6c87a398d4..1f07b6946f 100644 --- a/cli/command/node/inspect_test.go +++ b/cli/command/node/inspect_test.go @@ -20,7 +20,7 @@ func TestNodeInspectErrors(t *testing.T) { args []string flags map[string]string nodeInspectFunc func() (client.NodeInspectResult, error) - infoFunc func() (system.Info, error) + infoFunc func() (client.SystemInfoResult, error) expectedError string }{ { @@ -28,8 +28,8 @@ func TestNodeInspectErrors(t *testing.T) { }, { args: []string{"self"}, - infoFunc: func() (system.Info, error) { - return system.Info{}, errors.New("error asking for node info") + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, errors.New("error asking for node info") }, expectedError: "error asking for node info", }, @@ -38,8 +38,8 @@ func TestNodeInspectErrors(t *testing.T) { nodeInspectFunc: func() (client.NodeInspectResult, error) { return client.NodeInspectResult{}, errors.New("error inspecting the node") }, - infoFunc: func() (system.Info, error) { - return system.Info{}, errors.New("error asking for node info") + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, errors.New("error asking for node info") }, expectedError: "error inspecting the node", }, @@ -48,8 +48,12 @@ func TestNodeInspectErrors(t *testing.T) { nodeInspectFunc: func() (client.NodeInspectResult, error) { return client.NodeInspectResult{}, errors.New("error inspecting the node") }, - infoFunc: func() (system.Info, error) { - return system.Info{Swarm: swarm.Info{NodeID: "abc"}}, nil + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{ + Info: system.Info{ + Swarm: swarm.Info{NodeID: "abc"}, + }, + }, nil }, expectedError: "error inspecting the node", }, @@ -58,8 +62,8 @@ func TestNodeInspectErrors(t *testing.T) { flags: map[string]string{ "pretty": "true", }, - infoFunc: func() (system.Info, error) { - return system.Info{}, errors.New("error asking for node info") + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, errors.New("error asking for node info") }, expectedError: "error asking for node info", }, diff --git a/cli/command/node/list.go b/cli/command/node/list.go index 94a98dedf4..526ec65587 100644 --- a/cli/command/node/list.go +++ b/cli/command/node/list.go @@ -10,7 +10,6 @@ import ( flagsHelper "github.com/docker/cli/cli/flags" "github.com/docker/cli/opts" "github.com/fvbommel/sortorder" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" "github.com/spf13/cobra" ) @@ -53,10 +52,10 @@ func runList(ctx context.Context, dockerCLI command.Cli, options listOptions) er return err } - var info system.Info + var info client.SystemInfoResult if len(res.Items) > 0 && !options.quiet { // only non-empty nodes and not quiet, should we call /info api - info, err = apiClient.Info(ctx) + info, err = apiClient.Info(ctx, client.InfoOptions{}) if err != nil { return err } diff --git a/cli/command/node/list_test.go b/cli/command/node/list_test.go index 08afce5428..b2cc4611d1 100644 --- a/cli/command/node/list_test.go +++ b/cli/command/node/list_test.go @@ -19,7 +19,7 @@ import ( func TestNodeListErrorOnAPIFailure(t *testing.T) { testCases := []struct { nodeListFunc func() (client.NodeListResult, error) - infoFunc func() (system.Info, error) + infoFunc func() (client.SystemInfoResult, error) expectedError string }{ { @@ -36,8 +36,8 @@ func TestNodeListErrorOnAPIFailure(t *testing.T) { }, }, nil }, - infoFunc: func() (system.Info, error) { - return system.Info{}, errors.New("error asking for node info") + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, errors.New("error asking for node info") }, expectedError: "error asking for node info", }, @@ -65,10 +65,10 @@ func TestNodeList(t *testing.T) { }, }, nil }, - infoFunc: func() (system.Info, error) { - return system.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID1", + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{ + Info: system.Info{ + Swarm: swarm.Info{NodeID: "nodeID1"}, }, }, nil }, @@ -106,10 +106,10 @@ func TestNodeListDefaultFormatFromConfig(t *testing.T) { }, }, nil }, - infoFunc: func() (system.Info, error) { - return system.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID1", + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{ + Info: system.Info{ + Swarm: swarm.Info{NodeID: "nodeID1"}, }, }, nil }, @@ -132,10 +132,10 @@ func TestNodeListFormat(t *testing.T) { }, }, nil }, - infoFunc: func() (system.Info, error) { - return system.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID1", + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{ + Info: system.Info{ + Swarm: swarm.Info{NodeID: "nodeID1"}, }, }, nil }, diff --git a/cli/command/node/ps_test.go b/cli/command/node/ps_test.go index 342e871ae4..16b93a21c8 100644 --- a/cli/command/node/ps_test.go +++ b/cli/command/node/ps_test.go @@ -11,7 +11,6 @@ import ( "github.com/docker/cli/internal/test" "github.com/docker/cli/internal/test/builders" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" "gotest.tools/v3/assert" "gotest.tools/v3/golden" @@ -21,15 +20,14 @@ func TestNodePsErrors(t *testing.T) { testCases := []struct { args []string flags map[string]string - infoFunc func() (system.Info, error) + infoFunc func() (client.SystemInfoResult, error) nodeInspectFunc func() (client.NodeInspectResult, error) taskListFunc func(options client.TaskListOptions) (client.TaskListResult, error) - taskInspectFunc func(taskID string) (client.TaskInspectResult, error) expectedError string }{ { - infoFunc: func() (system.Info, error) { - return system.Info{}, errors.New("error asking for node info") + infoFunc: func() (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, errors.New("error asking for node info") }, expectedError: "error asking for node info", }, @@ -52,7 +50,6 @@ func TestNodePsErrors(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ infoFunc: tc.infoFunc, nodeInspectFunc: tc.nodeInspectFunc, - taskInspectFunc: tc.taskInspectFunc, taskListFunc: tc.taskListFunc, }) cmd := newPsCommand(cli) @@ -71,7 +68,6 @@ func TestNodePs(t *testing.T) { name string args []string flags map[string]string - infoFunc func() (system.Info, error) nodeInspectFunc func() (client.NodeInspectResult, error) taskListFunc func(options client.TaskListOptions) (client.TaskListResult, error) taskInspectFunc func(taskID string) (client.TaskInspectResult, error) @@ -148,7 +144,6 @@ func TestNodePs(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { cli := test.NewFakeCli(&fakeClient{ - infoFunc: tc.infoFunc, nodeInspectFunc: tc.nodeInspectFunc, taskInspectFunc: tc.taskInspectFunc, taskListFunc: tc.taskListFunc, diff --git a/cli/command/plugin/client_test.go b/cli/command/plugin/client_test.go index 453740e03f..d501ab7d76 100644 --- a/cli/command/plugin/client_test.go +++ b/cli/command/plugin/client_test.go @@ -5,7 +5,6 @@ import ( "io" "net/http" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) @@ -70,8 +69,8 @@ func (c *fakeClient) PluginInspect(_ context.Context, name string, _ client.Plug return client.PluginInspectResult{}, nil } -func (*fakeClient) Info(context.Context) (system.Info, error) { - return system.Info{}, nil +func (*fakeClient) Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, nil } func (c *fakeClient) PluginUpgrade(_ context.Context, name string, options client.PluginUpgradeOptions) (client.PluginUpgradeResult, error) { diff --git a/cli/command/registry/login.go b/cli/command/registry/login.go index 9529a7b043..fb138f8bfd 100644 --- a/cli/command/registry/login.go +++ b/cli/command/registry/login.go @@ -160,25 +160,32 @@ func loginWithStoredCredentials(ctx context.Context, dockerCLI command.Cli, auth _, _ = fmt.Fprint(dockerCLI.Err(), "\n\n") - response, err := dockerCLI.Client().RegistryLogin(ctx, authConfig) + resp, err := dockerCLI.Client().RegistryLogin(ctx, client.RegistryLoginOptions{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + }) if err != nil { if errdefs.IsUnauthorized(err) { _, _ = fmt.Fprintln(dockerCLI.Err(), "Stored credentials invalid or expired") } else { _, _ = fmt.Fprintln(dockerCLI.Err(), "Login did not succeed, error:", err) } + // TODO(thaJeztah): should this return the error here, or is there a reasong for continuing? } - if response.IdentityToken != "" { + if resp.Auth.IdentityToken != "" { authConfig.Password = "" - authConfig.IdentityToken = response.IdentityToken + authConfig.IdentityToken = resp.Auth.IdentityToken } if err := storeCredentials(dockerCLI.ConfigFile(), authConfig); err != nil { return "", err } - return response.Status, err + return resp.Auth.Status, err } func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, defaultUsername, serverAddress string) (msg string, _ error) { @@ -215,20 +222,26 @@ func loginWithUsernameAndPassword(ctx context.Context, dockerCLI command.Cli, op return "", err } - response, err := loginWithRegistry(ctx, dockerCLI.Client(), authConfig) + res, err := loginWithRegistry(ctx, dockerCLI.Client(), client.RegistryLoginOptions{ + Username: authConfig.Username, + Password: authConfig.Password, + ServerAddress: authConfig.ServerAddress, + IdentityToken: authConfig.IdentityToken, + RegistryToken: authConfig.RegistryToken, + }) if err != nil { return "", err } - if response.IdentityToken != "" { + if res.Auth.IdentityToken != "" { authConfig.Password = "" - authConfig.IdentityToken = response.IdentityToken + authConfig.IdentityToken = res.Auth.IdentityToken } if err = storeCredentials(dockerCLI.ConfigFile(), authConfig); err != nil { return "", err } - return response.Status, nil + return res.Auth.Status, nil } func loginWithDeviceCodeFlow(ctx context.Context, dockerCLI command.Cli) (msg string, _ error) { @@ -238,13 +251,13 @@ func loginWithDeviceCodeFlow(ctx context.Context, dockerCLI command.Cli) (msg st return "", err } - response, err := loginWithRegistry(ctx, dockerCLI.Client(), registrytypes.AuthConfig{ + response, err := loginWithRegistry(ctx, dockerCLI.Client(), client.RegistryLoginOptions{ Username: authConfig.Username, Password: authConfig.Password, ServerAddress: authConfig.ServerAddress, // TODO(thaJeztah): Are these expected to be included? - Auth: authConfig.Auth, + // Auth: authConfig.Auth, IdentityToken: authConfig.IdentityToken, RegistryToken: authConfig.RegistryToken, }) @@ -265,7 +278,7 @@ func loginWithDeviceCodeFlow(ctx context.Context, dockerCLI command.Cli) (msg st return "", err } - return response.Status, nil + return response.Auth.Status, nil } func storeCredentials(cfg *configfile.ConfigFile, authConfig registrytypes.AuthConfig) error { @@ -286,32 +299,42 @@ func storeCredentials(cfg *configfile.ConfigFile, authConfig registrytypes.AuthC return nil } -func loginWithRegistry(ctx context.Context, apiClient client.SystemAPIClient, authConfig registrytypes.AuthConfig) (*registrytypes.AuthenticateOKBody, error) { - response, err := apiClient.RegistryLogin(ctx, authConfig) +func loginWithRegistry(ctx context.Context, apiClient client.SystemAPIClient, options client.RegistryLoginOptions) (client.RegistryLoginResult, error) { + res, err := apiClient.RegistryLogin(ctx, options) if err != nil { if client.IsErrConnectionFailed(err) { // daemon isn't responding; attempt to login client side. - return loginClientSide(ctx, authConfig) + return loginClientSide(ctx, options) } - return nil, err + return client.RegistryLoginResult{}, err } - return &response, nil + return res, nil } -func loginClientSide(ctx context.Context, auth registrytypes.AuthConfig) (*registrytypes.AuthenticateOKBody, error) { +func loginClientSide(ctx context.Context, options client.RegistryLoginOptions) (client.RegistryLoginResult, error) { svc, err := registry.NewService(registry.ServiceOptions{}) if err != nil { - return nil, err + return client.RegistryLoginResult{}, err + } + + auth := registrytypes.AuthConfig{ + Username: options.Username, + Password: options.Password, + ServerAddress: options.ServerAddress, + IdentityToken: options.IdentityToken, + RegistryToken: options.RegistryToken, } token, err := svc.Auth(ctx, &auth, command.UserAgent()) if err != nil { - return nil, err + return client.RegistryLoginResult{}, err } - return ®istrytypes.AuthenticateOKBody{ - Status: "Login Succeeded", - IdentityToken: token, + return client.RegistryLoginResult{ + Auth: registrytypes.AuthenticateOKBody{ + Status: "Login Succeeded", + IdentityToken: token, + }, }, nil } diff --git a/cli/command/registry/login_test.go b/cli/command/registry/login_test.go index 62ef1a66d1..fba83e55a5 100644 --- a/cli/command/registry/login_test.go +++ b/cli/command/registry/login_test.go @@ -16,7 +16,6 @@ import ( "github.com/docker/cli/internal/registry" "github.com/docker/cli/internal/test" registrytypes "github.com/moby/moby/api/types/registry" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -34,23 +33,23 @@ type fakeClient struct { client.Client } -func (*fakeClient) Info(context.Context) (system.Info, error) { - return system.Info{}, nil +func (*fakeClient) Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, nil } -func (*fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) { - if auth.Password == expiredPassword { - return registrytypes.AuthenticateOKBody{}, errors.New("Invalid Username or Password") +func (*fakeClient) RegistryLogin(_ context.Context, options client.RegistryLoginOptions) (client.RegistryLoginResult, error) { + if options.Password == expiredPassword { + return client.RegistryLoginResult{}, errors.New("invalid Username or Password") } - if auth.Password == useToken { - return registrytypes.AuthenticateOKBody{ - IdentityToken: auth.Password, + if options.Password == useToken { + return client.RegistryLoginResult{ + Auth: registrytypes.AuthenticateOKBody{IdentityToken: options.Password}, }, nil } - if auth.Username == unknownUser { - return registrytypes.AuthenticateOKBody{}, errors.New(errUnknownUser) + if options.Username == unknownUser { + return client.RegistryLoginResult{}, errors.New(errUnknownUser) } - return registrytypes.AuthenticateOKBody{}, nil + return client.RegistryLoginResult{}, nil } func TestLoginWithCredStoreCreds(t *testing.T) { diff --git a/cli/command/service/client_test.go b/cli/command/service/client_test.go index 0e72b13a89..6e73940a88 100644 --- a/cli/command/service/client_test.go +++ b/cli/command/service/client_test.go @@ -5,7 +5,6 @@ import ( "github.com/docker/cli/internal/test/builders" "github.com/moby/moby/api/types/swarm" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) @@ -15,7 +14,7 @@ type fakeClient struct { 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) + infoFunc func(ctx context.Context) (client.SystemInfoResult, error) networkInspectFunc func(ctx context.Context, networkID string, options client.NetworkInspectOptions) (client.NetworkInspectResult, error) nodeListFunc func(ctx context.Context, options client.NodeListOptions) (client.NodeListResult, error) } @@ -60,11 +59,11 @@ func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, option return client.ServiceUpdateResult{}, nil } -func (f *fakeClient) Info(ctx context.Context) (system.Info, error) { - if f.infoFunc == nil { - return system.Info{}, nil +func (f *fakeClient) Info(ctx context.Context, _ client.InfoOptions) (client.SystemInfoResult, error) { + if f.infoFunc != nil { + return f.infoFunc(ctx) } - return f.infoFunc(ctx) + return client.SystemInfoResult{}, nil } func (f *fakeClient) NetworkInspect(ctx context.Context, networkID string, options client.NetworkInspectOptions) (client.NetworkInspectResult, error) { diff --git a/cli/command/service/ps_test.go b/cli/command/service/ps_test.go index d2c0285756..0833d64a76 100644 --- a/cli/command/service/ps_test.go +++ b/cli/command/service/ps_test.go @@ -117,8 +117,12 @@ func TestUpdateNodeFilter(t *testing.T) { filter := make(client.Filters).Add("node", "one", "two", "self") apiClient := &fakeClient{ - infoFunc: func(_ context.Context) (system.Info, error) { - return system.Info{Swarm: swarm.Info{NodeID: selfNodeID}}, nil + infoFunc: func(_ context.Context) (client.SystemInfoResult, error) { + return client.SystemInfoResult{ + Info: system.Info{ + Swarm: swarm.Info{NodeID: selfNodeID}, + }, + }, nil }, } diff --git a/cli/command/stack/client_test.go b/cli/command/stack/client_test.go index 2855583f5b..118e7edf14 100644 --- a/cli/command/stack/client_test.go +++ b/cli/command/stack/client_test.go @@ -147,13 +147,13 @@ func (cli *fakeClient) ServiceRemove(_ context.Context, serviceID string, _ clie return client.ServiceRemoveResult{}, nil } -func (cli *fakeClient) NetworkRemove(_ context.Context, networkID string) error { +func (cli *fakeClient) NetworkRemove(_ context.Context, networkID string, _ client.NetworkRemoveOptions) (client.NetworkRemoveResult, error) { if cli.networkRemoveFunc != nil { - return cli.networkRemoveFunc(networkID) + return client.NetworkRemoveResult{}, cli.networkRemoveFunc(networkID) } cli.removedNetworks = append(cli.removedNetworks, networkID) - return nil + return client.NetworkRemoveResult{}, nil } func (cli *fakeClient) SecretRemove(_ context.Context, secretID string, _ client.SecretRemoveOptions) (client.SecretRemoveResult, error) { diff --git a/cli/command/stack/deploy.go b/cli/command/stack/deploy.go index d2d492acf1..3618870f60 100644 --- a/cli/command/stack/deploy.go +++ b/cli/command/stack/deploy.go @@ -10,6 +10,7 @@ import ( "github.com/docker/cli/cli/compose/convert" composetypes "github.com/docker/cli/cli/compose/types" "github.com/moby/moby/api/types/swarm" + "github.com/moby/moby/client" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -93,11 +94,11 @@ func runDeploy(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, // create services, but the API call for creating a network does not return a // proper status code when it can't create a network in the "global" scope. func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error { - info, err := dockerCli.Client().Info(ctx) + res, err := dockerCli.Client().Info(ctx, client.InfoOptions{}) if err != nil { return err } - if !info.Swarm.ControlAvailable { + if !res.Info.Swarm.ControlAvailable { return errors.New(`this node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again`) } return nil diff --git a/cli/command/stack/remove.go b/cli/command/stack/remove.go index 337f9d4ba7..90ab2df29b 100644 --- a/cli/command/stack/remove.go +++ b/cli/command/stack/remove.go @@ -119,7 +119,7 @@ func removeNetworks(ctx context.Context, dockerCLI command.Cli, networks []netwo var hasError bool for _, nw := range networks { _, _ = fmt.Fprintln(dockerCLI.Out(), "Removing network", nw.Name) - if err := dockerCLI.Client().NetworkRemove(ctx, nw.ID); err != nil { + if _, err := dockerCLI.Client().NetworkRemove(ctx, nw.ID, client.NetworkRemoveOptions{}); err != nil { hasError = true _, _ = fmt.Fprintf(dockerCLI.Err(), "Failed to remove network %s: %s", nw.ID, err) } diff --git a/cli/command/swarm/client_test.go b/cli/command/swarm/client_test.go index 8c5a42a881..ea2d24d131 100644 --- a/cli/command/swarm/client_test.go +++ b/cli/command/swarm/client_test.go @@ -20,11 +20,14 @@ type fakeClient struct { swarmUnlockFunc func(client.SwarmUnlockOptions) (client.SwarmUnlockResult, error) } -func (cli *fakeClient) Info(context.Context) (system.Info, error) { +func (cli *fakeClient) Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error) { if cli.infoFunc != nil { - return cli.infoFunc() + inf, err := cli.infoFunc() + return client.SystemInfoResult{ + Info: inf, + }, err } - return system.Info{}, nil + return client.SystemInfoResult{}, nil } func (cli *fakeClient) NodeInspect(context.Context, string, client.NodeInspectOptions) (client.NodeInspectResult, error) { diff --git a/cli/command/swarm/join.go b/cli/command/swarm/join.go index 8f1a75e5c5..3fd68fe9da 100644 --- a/cli/command/swarm/join.go +++ b/cli/command/swarm/join.go @@ -78,12 +78,12 @@ func runJoin(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, o return err } - info, err := apiClient.Info(ctx) + res, err := apiClient.Info(ctx, client.InfoOptions{}) if err != nil { return err } - if info.Swarm.ControlAvailable { + if res.Info.Swarm.ControlAvailable { _, _ = fmt.Fprintln(dockerCLI.Out(), "This node joined a swarm as a manager.") } else { _, _ = fmt.Fprintln(dockerCLI.Out(), "This node joined a swarm as a worker.") diff --git a/cli/command/swarm/join_token.go b/cli/command/swarm/join_token.go index 4639035c78..a1c01ec3c9 100644 --- a/cli/command/swarm/join_token.go +++ b/cli/command/swarm/join_token.go @@ -90,12 +90,12 @@ func runJoinToken(ctx context.Context, dockerCLI command.Cli, opts joinTokenOpti return nil } - info, err := apiClient.Info(ctx) + infoResp, err := apiClient.Info(ctx, client.InfoOptions{}) if err != nil { return err } - return printJoinCommand(ctx, dockerCLI, info.Swarm.NodeID, worker, manager) + return printJoinCommand(ctx, dockerCLI, infoResp.Info.Swarm.NodeID, worker, manager) } func printJoinCommand(ctx context.Context, dockerCLI command.Cli, nodeID string, worker bool, manager bool) error { diff --git a/cli/command/swarm/unlock.go b/cli/command/swarm/unlock.go index 08e130a67e..bf15ed2868 100644 --- a/cli/command/swarm/unlock.go +++ b/cli/command/swarm/unlock.go @@ -41,12 +41,12 @@ func runUnlock(ctx context.Context, dockerCLI command.Cli) error { // First see if the node is actually part of a swarm, and if it is actually locked first. // If it's in any other state than locked, don't ask for the key. - info, err := apiClient.Info(ctx) + res, err := apiClient.Info(ctx, client.InfoOptions{}) if err != nil { return err } - switch info.Swarm.LocalNodeState { + switch res.Info.Swarm.LocalNodeState { case swarm.LocalNodeStateInactive: return errors.New("error: this node is not part of a swarm") case swarm.LocalNodeStateLocked: diff --git a/cli/command/system/client_test.go b/cli/command/system/client_test.go index 94ed45fa1e..b2099d3324 100644 --- a/cli/command/system/client_test.go +++ b/cli/command/system/client_test.go @@ -6,7 +6,6 @@ import ( "github.com/moby/moby/api/types" "github.com/moby/moby/api/types/container" "github.com/moby/moby/api/types/events" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" ) @@ -18,7 +17,7 @@ type fakeClient struct { containerPruneFunc func(ctx context.Context, options client.ContainerPruneOptions) (client.ContainerPruneResult, error) eventsFn func(context.Context, client.EventsListOptions) (<-chan events.Message, <-chan error) imageListFunc func(ctx context.Context, options client.ImageListOptions) (client.ImageListResult, error) - infoFunc func(ctx context.Context) (system.Info, error) + infoFunc func(ctx context.Context, options client.InfoOptions) (client.SystemInfoResult, error) networkListFunc func(ctx context.Context, options client.NetworkListOptions) (client.NetworkListResult, error) networkPruneFunc func(ctx context.Context, options client.NetworkPruneOptions) (client.NetworkPruneResult, error) nodeListFunc func(ctx context.Context, options client.NodeListOptions) (client.NodeListResult, error) @@ -30,11 +29,14 @@ func (cli *fakeClient) ClientVersion() string { return cli.version } -func (cli *fakeClient) ContainerList(ctx context.Context, options client.ContainerListOptions) ([]container.Summary, error) { +func (cli *fakeClient) ContainerList(ctx context.Context, options client.ContainerListOptions) (client.ContainerListResult, error) { if cli.containerListFunc != nil { - return cli.containerListFunc(ctx, options) + res, err := cli.containerListFunc(ctx, options) + return client.ContainerListResult{ + Items: res, + }, err } - return []container.Summary{}, nil + return client.ContainerListResult{}, nil } func (cli *fakeClient) ContainersPrune(ctx context.Context, opts client.ContainerPruneOptions) (client.ContainerPruneResult, error) { @@ -44,8 +46,12 @@ func (cli *fakeClient) ContainersPrune(ctx context.Context, opts client.Containe return client.ContainerPruneResult{}, nil } -func (cli *fakeClient) Events(ctx context.Context, opts client.EventsListOptions) (<-chan events.Message, <-chan error) { - return cli.eventsFn(ctx, opts) +func (cli *fakeClient) Events(ctx context.Context, opts client.EventsListOptions) client.EventsResult { + eventC, errC := cli.eventsFn(ctx, opts) + return client.EventsResult{ + Messages: eventC, + Err: errC, + } } func (cli *fakeClient) ImageList(ctx context.Context, options client.ImageListOptions) (client.ImageListResult, error) { @@ -55,11 +61,11 @@ func (cli *fakeClient) ImageList(ctx context.Context, options client.ImageListOp return client.ImageListResult{}, nil } -func (cli *fakeClient) Info(ctx context.Context) (system.Info, error) { +func (cli *fakeClient) Info(ctx context.Context, options client.InfoOptions) (client.SystemInfoResult, error) { if cli.infoFunc != nil { - return cli.infoFunc(ctx) + return cli.infoFunc(ctx, options) } - return system.Info{}, nil + return client.SystemInfoResult{}, nil } func (cli *fakeClient) NetworkList(ctx context.Context, options client.NetworkListOptions) (client.NetworkListResult, error) { diff --git a/cli/command/system/completion.go b/cli/command/system/completion.go index 55540de078..058dd4b29a 100644 --- a/cli/command/system/completion.go +++ b/cli/command/system/completion.go @@ -187,11 +187,11 @@ func containerNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command, // daemonNames contacts the API to get name and ID of the current docker daemon. // In case of an error, an empty list is returned. func daemonNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string { - info, err := dockerCLI.Client().Info(cmd.Context()) + res, err := dockerCLI.Client().Info(cmd.Context(), client.InfoOptions{}) if err != nil { return []string{} } - return []string{info.Name, info.ID} + return []string{res.Info.Name, res.Info.ID} } // imageNames contacts the API to get a list of image names. diff --git a/cli/command/system/completion_test.go b/cli/command/system/completion_test.go index 48890dc710..0095ce598e 100644 --- a/cli/command/system/completion_test.go +++ b/cli/command/system/completion_test.go @@ -48,10 +48,12 @@ func TestCompleteEventFilter(t *testing.T) { }, { client: &fakeClient{ - infoFunc: func(ctx context.Context) (system.Info, error) { - return system.Info{ - ID: "daemon-id", - Name: "daemon-name", + infoFunc: func(_ context.Context, _ client.InfoOptions) (client.SystemInfoResult, error) { + return client.SystemInfoResult{ + Info: system.Info{ + ID: "daemon-id", + Name: "daemon-name", + }, }, nil }, }, @@ -60,8 +62,8 @@ func TestCompleteEventFilter(t *testing.T) { }, { client: &fakeClient{ - infoFunc: func(ctx context.Context) (system.Info, error) { - return system.Info{}, errors.New("API error") + infoFunc: func(_ context.Context, _ client.InfoOptions) (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, errors.New("API error") }, }, toComplete: "daemon=", diff --git a/cli/command/system/events.go b/cli/command/system/events.go index 6daf643356..03f465fabd 100644 --- a/cli/command/system/events.go +++ b/cli/command/system/events.go @@ -65,7 +65,7 @@ func runEvents(ctx context.Context, dockerCLI command.Cli, options *eventsOption } } ctx, cancel := context.WithCancel(ctx) - evts, errs := dockerCLI.Client().Events(ctx, client.EventsListOptions{ + eventRes := dockerCLI.Client().Events(ctx, client.EventsListOptions{ Since: options.since, Until: options.until, Filters: options.filter.Value(), @@ -76,11 +76,11 @@ func runEvents(ctx context.Context, dockerCLI command.Cli, options *eventsOption for { select { - case event := <-evts: + case event := <-eventRes.Messages: if err := handleEvent(out, event, tmpl); err != nil { return err } - case err := <-errs: + case err := <-eventRes.Err: if err == io.EOF { return nil } @@ -93,8 +93,11 @@ func handleEvent(out io.Writer, event events.Message, tmpl *template.Template) e if tmpl == nil { return prettyPrintEvent(out, event) } - - return formatEvent(out, event, tmpl) + if err := tmpl.Execute(out, event); err != nil { + return err + } + _, _ = out.Write([]byte{'\n'}) + return nil } func makeTemplate(format string) (*template.Template, error) { @@ -145,8 +148,3 @@ func prettyPrintEvent(out io.Writer, event events.Message) error { _, _ = fmt.Fprint(out, "\n") return nil } - -func formatEvent(out io.Writer, event events.Message, tmpl *template.Template) error { - defer out.Write([]byte{'\n'}) - return tmpl.Execute(out, event) -} diff --git a/cli/command/system/info.go b/cli/command/system/info.go index 989359eea9..7baed0e987 100644 --- a/cli/command/system/info.go +++ b/cli/command/system/info.go @@ -117,7 +117,7 @@ func runInfo(ctx context.Context, cmd *cobra.Command, dockerCli command.Cli, opt // if a connection error occurs, it will be returned as an error. // other errors are appended to the info.ServerErrors field. func addServerInfo(ctx context.Context, dockerCli command.Cli, format string, info *dockerInfo) error { - dinfo, err := dockerCli.Client().Info(ctx) + res, err := dockerCli.Client().Info(ctx, client.InfoOptions{}) if err != nil { // if no format is provided and we have an error, don't print the server info if format == "" { @@ -137,7 +137,7 @@ func addServerInfo(ctx context.Context, dockerCli command.Cli, format string, in } // only assign the server info if we have no error - info.Info = &dinfo + info.Info = &res.Info return nil } diff --git a/cli/command/system/inspect.go b/cli/command/system/inspect.go index b2359bfb12..5dfe556d24 100644 --- a/cli/command/system/inspect.go +++ b/cli/command/system/inspect.go @@ -233,12 +233,12 @@ func inspectAll(ctx context.Context, dockerCLI command.Cli, getSize bool, typeCo // isSwarmManager does an Info API call to verify that the daemon is // a swarm manager. isSwarmManager := func() bool { - info, err := dockerCLI.Client().Info(ctx) + res, err := dockerCLI.Client().Info(ctx, client.InfoOptions{}) if err != nil { _, _ = fmt.Fprintln(dockerCLI.Err(), err) return false } - return info.Swarm.ControlAvailable + return res.Info.Swarm.ControlAvailable } return func(ref string) (any, []byte, error) { diff --git a/cli/command/trust/inspect_pretty_test.go b/cli/command/trust/inspect_pretty_test.go index 8cb79cff90..d23f0aaeb4 100644 --- a/cli/command/trust/inspect_pretty_test.go +++ b/cli/command/trust/inspect_pretty_test.go @@ -11,7 +11,6 @@ import ( "github.com/docker/cli/cli/trust" "github.com/docker/cli/internal/test" notaryfake "github.com/docker/cli/internal/test/notary" - "github.com/moby/moby/api/types/system" "github.com/moby/moby/client" "github.com/theupdateframework/notary" notaryclient "github.com/theupdateframework/notary/client" @@ -35,8 +34,8 @@ type fakeStreamResult struct { 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 +func (*fakeClient) Info(context.Context, client.InfoOptions) (client.SystemInfoResult, error) { + return client.SystemInfoResult{}, nil } func (*fakeClient) ImageInspect(context.Context, string, ...client.ImageInspectOption) (client.ImageInspectResult, error) { diff --git a/cli/command/volume/client_test.go b/cli/command/volume/client_test.go index c0b625a668..cd11a3d7d2 100644 --- a/cli/command/volume/client_test.go +++ b/cli/command/volume/client_test.go @@ -43,9 +43,9 @@ func (c *fakeClient) VolumesPrune(_ context.Context, opts client.VolumePruneOpti return client.VolumePruneResult{}, nil } -func (c *fakeClient) VolumeRemove(_ context.Context, volumeID string, options client.VolumeRemoveOptions) error { +func (c *fakeClient) VolumeRemove(_ context.Context, volumeID string, options client.VolumeRemoveOptions) (client.VolumeRemoveResult, error) { if c.volumeRemoveFunc != nil { - return c.volumeRemoveFunc(volumeID, options.Force) + return client.VolumeRemoveResult{}, c.volumeRemoveFunc(volumeID, options.Force) } - return nil + return client.VolumeRemoveResult{}, nil } diff --git a/cli/command/volume/remove.go b/cli/command/volume/remove.go index 96c240def5..4cfc04e7bb 100644 --- a/cli/command/volume/remove.go +++ b/cli/command/volume/remove.go @@ -37,7 +37,7 @@ func newRemoveCommand(dockerCLI command.Cli) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Force the removal of one or more volumes") - flags.SetAnnotation("force", "version", []string{"1.25"}) + _ = flags.SetAnnotation("force", "version", []string{"1.25"}) return cmd } @@ -46,7 +46,7 @@ func runRemove(ctx context.Context, dockerCLI command.Cli, opts *removeOptions) var errs []error for _, name := range opts.volumes { - err := apiClient.VolumeRemove(ctx, name, client.VolumeRemoveOptions{ + _, err := apiClient.VolumeRemove(ctx, name, client.VolumeRemoveOptions{ Force: opts.force, }) if err != nil { diff --git a/cli/command/volume/update.go b/cli/command/volume/update.go index 6ee09ce889..0d986051b8 100644 --- a/cli/command/volume/update.go +++ b/cli/command/volume/update.go @@ -58,11 +58,9 @@ func runUpdate(ctx context.Context, dockerCli command.Cli, volumeID, availabilit if flags.Changed("availability") { res.Volume.ClusterVolume.Spec.Availability = volume.Availability(availability) } - - return apiClient.VolumeUpdate( - ctx, res.Volume.ClusterVolume.ID, res.Volume.ClusterVolume.Version, - client.VolumeUpdateOptions{ - Spec: &res.Volume.ClusterVolume.Spec, - }, - ) + _, err = apiClient.VolumeUpdate(ctx, res.Volume.ClusterVolume.ID, client.VolumeUpdateOptions{ + Version: res.Volume.ClusterVolume.Version, + Spec: &res.Volume.ClusterVolume.Spec, + }) + return err } diff --git a/vendor.mod b/vendor.mod index 2130c01593..b0be232a27 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.20251028144225-90109a373da9 // master - github.com/moby/moby/client v0.1.0-beta.2.0.20251028144225-90109a373da9 // master + github.com/moby/moby/api v1.52.0-beta.2.0.20251029165853-ef17deb3a0fb // master + github.com/moby/moby/client v0.1.0-beta.2.0.20251029165853-ef17deb3a0fb // 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 55e213030e..ce0ba0edbb 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.20251028144225-90109a373da9 h1:DDumCtiHK751YhrY/tbUdMo5BN8dRarxbW4ScVh/KZg= -github.com/moby/moby/api v1.52.0-beta.2.0.20251028144225-90109a373da9/go.mod h1:v0K/motq8oWmx+rtApG1rBTIpQ8KUONUjpf+U73gags= -github.com/moby/moby/client v0.1.0-beta.2.0.20251028144225-90109a373da9 h1:iAQD/kAfqMAb2p48advqXGOT8eWyEv+Xge7KbcsZduk= -github.com/moby/moby/client v0.1.0-beta.2.0.20251028144225-90109a373da9/go.mod h1:1YrJTvhL771Q4xiwwe72NSS17lgsCF67xu8fEfSd77g= +github.com/moby/moby/api v1.52.0-beta.2.0.20251029165853-ef17deb3a0fb h1:t4RxpXuvv26rIVUBqUm0xgmaSmmTJTv5fzEDxg5piWE= +github.com/moby/moby/api v1.52.0-beta.2.0.20251029165853-ef17deb3a0fb/go.mod h1:v0K/motq8oWmx+rtApG1rBTIpQ8KUONUjpf+U73gags= +github.com/moby/moby/client v0.1.0-beta.2.0.20251029165853-ef17deb3a0fb h1:3F0iF/yIxE43JcK3rJp4k/TsVmfvFMgRyGT/tg+K1xI= +github.com/moby/moby/client v0.1.0-beta.2.0.20251029165853-ef17deb3a0fb/go.mod h1:1YrJTvhL771Q4xiwwe72NSS17lgsCF67xu8fEfSd77g= 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/network/connect_request.go b/vendor/github.com/moby/moby/api/types/network/connect_request.go new file mode 100644 index 0000000000..2ff14d3603 --- /dev/null +++ b/vendor/github.com/moby/moby/api/types/network/connect_request.go @@ -0,0 +1,20 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package network + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +// ConnectRequest NetworkConnectRequest represents the data to be used to connect a container to a network. +// +// swagger:model ConnectRequest +type ConnectRequest struct { + + // The ID or name of the container to connect to the network. + // Example: 3613f73ba0e4 + // Required: true + Container string `json:"Container"` + + // endpoint config + EndpointConfig *EndpointSettings `json:"EndpointConfig,omitempty"` +} diff --git a/vendor/github.com/moby/moby/api/types/network/disconnect_request.go b/vendor/github.com/moby/moby/api/types/network/disconnect_request.go new file mode 100644 index 0000000000..7b1f521e77 --- /dev/null +++ b/vendor/github.com/moby/moby/api/types/network/disconnect_request.go @@ -0,0 +1,21 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package network + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +// DisconnectRequest NetworkDisconnectRequest represents the data to be used to disconnect a container from a network. +// +// swagger:model DisconnectRequest +type DisconnectRequest struct { + + // The ID or name of the container to disconnect from the network. + // Example: 3613f73ba0e4 + // Required: true + Container string `json:"Container"` + + // Force the container to disconnect from the network. + // Example: false + Force bool `json:"Force"` +} diff --git a/vendor/github.com/moby/moby/client/client.go b/vendor/github.com/moby/moby/client/client.go index 643dfbdf8f..950f3adc75 100644 --- a/vendor/github.com/moby/moby/client/client.go +++ b/vendor/github.com/moby/moby/client/client.go @@ -259,23 +259,13 @@ func (cli *Client) Close() error { // be negotiated when making the actual requests, and for which cases // we cannot do the negotiation lazily. func (cli *Client) checkVersion(ctx context.Context) error { - if !cli.manualOverride && cli.negotiateVersion && !cli.negotiated.Load() { - // Ensure exclusive write access to version and negotiated fields - cli.negotiateLock.Lock() - defer cli.negotiateLock.Unlock() - - // May have been set during last execution of critical zone - if cli.negotiated.Load() { - return nil - } - - ping, err := cli.Ping(ctx, PingOptions{}) - if err != nil { - return err - } - return cli.negotiateAPIVersion(ping.APIVersion) + if cli.manualOverride || !cli.negotiateVersion || cli.negotiated.Load() { + return nil } - return nil + _, err := cli.Ping(ctx, PingOptions{ + NegotiateAPIVersion: true, + }) + return err } // getAPIPath returns the versioned request path to call the API. @@ -296,59 +286,6 @@ func (cli *Client) ClientVersion() string { return cli.version } -// NegotiateAPIVersion queries the API and updates the version to match the API -// version. NegotiateAPIVersion downgrades the client's API version to match the -// APIVersion if the ping version is lower than the default version. If the API -// version reported by the server is higher than the maximum version supported -// by the client, it uses the client's maximum version. -// -// If a manual override is in place, either through the "DOCKER_API_VERSION" -// ([EnvOverrideAPIVersion]) environment variable, or if the client is initialized -// with a fixed version ([WithVersion]), no negotiation is performed. -// -// If the API server's ping response does not contain an API version, or if the -// client did not get a successful ping response, it assumes it is connected with -// an old daemon that does not support API version negotiation, in which case it -// downgrades to the lowest supported API version. -func (cli *Client) NegotiateAPIVersion(ctx context.Context) { - if !cli.manualOverride { - // Avoid concurrent modification of version-related fields - cli.negotiateLock.Lock() - defer cli.negotiateLock.Unlock() - - ping, err := cli.Ping(ctx, PingOptions{}) - if err != nil { - // FIXME(thaJeztah): Ping returns an error when failing to connect to the API; we should not swallow the error here, and instead returning it. - return - } - // FIXME(thaJeztah): we should not swallow the error here, and instead returning it. - _ = cli.negotiateAPIVersion(ping.APIVersion) - } -} - -// NegotiateAPIVersionPing downgrades the client's API version to match the -// APIVersion in the ping response. If the API version in pingResponse is higher -// than the maximum version supported by the client, it uses the client's maximum -// version. -// -// If a manual override is in place, either through the "DOCKER_API_VERSION" -// ([EnvOverrideAPIVersion]) environment variable, or if the client is initialized -// with a fixed version ([WithVersion]), no negotiation is performed. -// -// If the API server's ping response does not contain an API version, it falls -// back to the oldest API version supported. -func (cli *Client) NegotiateAPIVersionPing(pingResponse PingResult) { - // TODO(thaJeztah): should this take a "Ping" option? It only consumes the version. This method should be removed overall and not be exported. - if !cli.manualOverride { - // Avoid concurrent modification of version-related fields - cli.negotiateLock.Lock() - defer cli.negotiateLock.Unlock() - - // FIXME(thaJeztah): we should not swallow the error here, and instead returning it. - _ = cli.negotiateAPIVersion(pingResponse.APIVersion) - } -} - // negotiateAPIVersion updates the version to match the API version from // the ping response. It falls back to the lowest version supported if the // API version is empty, or returns an error if the API version is lower than diff --git a/vendor/github.com/moby/moby/client/client_interfaces.go b/vendor/github.com/moby/moby/client/client_interfaces.go index 9c69782e55..9e7d4c1641 100644 --- a/vendor/github.com/moby/moby/client/client_interfaces.go +++ b/vendor/github.com/moby/moby/client/client_interfaces.go @@ -6,11 +6,7 @@ import ( "net" "github.com/moby/moby/api/types" - "github.com/moby/moby/api/types/container" - "github.com/moby/moby/api/types/events" "github.com/moby/moby/api/types/network" - "github.com/moby/moby/api/types/registry" - "github.com/moby/moby/api/types/swarm" "github.com/moby/moby/api/types/system" ) @@ -32,8 +28,6 @@ type stableAPIClient interface { ClientVersion() string DaemonHost() string ServerVersion(ctx context.Context) (types.Version, error) - NegotiateAPIVersion(ctx context.Context) - NegotiateAPIVersionPing(PingResult) HijackDialer Dialer() func(context.Context) (net.Conn, error) Close() error @@ -62,26 +56,26 @@ type ContainerAPIClient interface { 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) + ContainerExport(ctx context.Context, container string, options ContainerExportOptions) (ContainerExportResult, error) ContainerInspect(ctx context.Context, container string, options ContainerInspectOptions) (ContainerInspectResult, error) ContainerKill(ctx context.Context, container string, options ContainerKillOptions) (ContainerKillResult, error) - ContainerList(ctx context.Context, options ContainerListOptions) ([]container.Summary, error) - ContainerLogs(ctx context.Context, container string, options ContainerLogsOptions) (io.ReadCloser, error) + ContainerList(ctx context.Context, options ContainerListOptions) (ContainerListResult, error) + ContainerLogs(ctx context.Context, container string, options ContainerLogsOptions) (ContainerLogsResult, error) ContainerPause(ctx context.Context, container string, options ContainerPauseOptions) (ContainerPauseResult, error) ContainerRemove(ctx context.Context, container string, options ContainerRemoveOptions) (ContainerRemoveResult, error) - ContainerRename(ctx context.Context, container, newContainerName string) error + ContainerRename(ctx context.Context, container string, options ContainerRenameOptions) (ContainerRenameResult, error) ContainerResize(ctx context.Context, container string, options ContainerResizeOptions) (ContainerResizeResult, error) ContainerRestart(ctx context.Context, container string, options ContainerRestartOptions) (ContainerRestartResult, error) - ContainerStatPath(ctx context.Context, container, path string) (container.PathStat, error) + ContainerStatPath(ctx context.Context, container string, options ContainerStatPathOptions) (ContainerStatPathResult, error) ContainerStats(ctx context.Context, container string, options ContainerStatsOptions) (ContainerStatsResult, error) ContainerStart(ctx context.Context, container string, options ContainerStartOptions) (ContainerStartResult, error) ContainerStop(ctx context.Context, container string, options ContainerStopOptions) (ContainerStopResult, error) - ContainerTop(ctx context.Context, container string, arguments []string) (container.TopResponse, error) - ContainerUnpause(ctx context.Context, container string, options ContainerUnPauseOptions) (ContainerUnPauseResult, error) - ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) - ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) - CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, container.PathStat, error) - CopyToContainer(ctx context.Context, container, path string, content io.Reader, options CopyToContainerOptions) error + ContainerTop(ctx context.Context, container string, options ContainerTopOptions) (ContainerTopResult, error) + ContainerUnpause(ctx context.Context, container string, options ContainerUnpauseOptions) (ContainerUnpauseResult, error) + ContainerUpdate(ctx context.Context, container string, updateConfig ContainerUpdateOptions) (ContainerUpdateResult, error) + ContainerWait(ctx context.Context, container string, options ContainerWaitOptions) ContainerWaitResult + CopyFromContainer(ctx context.Context, container string, options CopyFromContainerOptions) (CopyFromContainerResult, error) + CopyToContainer(ctx context.Context, container string, options CopyToContainerOptions) (CopyToContainerResult, error) ContainersPrune(ctx context.Context, opts ContainerPruneOptions) (ContainerPruneResult, error) } @@ -122,12 +116,12 @@ type ImageAPIClient interface { // NetworkAPIClient defines API client methods for the networks type NetworkAPIClient interface { - NetworkConnect(ctx context.Context, network, container string, config *network.EndpointSettings) error + NetworkConnect(ctx context.Context, network string, options NetworkConnectOptions) (NetworkConnectResult, error) NetworkCreate(ctx context.Context, name string, options NetworkCreateOptions) (network.CreateResponse, error) - NetworkDisconnect(ctx context.Context, network, container string, force bool) error + NetworkDisconnect(ctx context.Context, network string, options NetworkDisconnectOptions) (NetworkDisconnectResult, error) NetworkInspect(ctx context.Context, network string, options NetworkInspectOptions) (NetworkInspectResult, error) NetworkList(ctx context.Context, options NetworkListOptions) (NetworkListResult, error) - NetworkRemove(ctx context.Context, network string) error + NetworkRemove(ctx context.Context, network string, options NetworkRemoveOptions) (NetworkRemoveResult, error) NetworksPrune(ctx context.Context, opts NetworkPruneOptions) (NetworkPruneResult, error) } @@ -179,9 +173,9 @@ type SwarmAPIClient interface { // SystemAPIClient defines API client methods for the system type SystemAPIClient interface { - Events(ctx context.Context, options EventsListOptions) (<-chan events.Message, <-chan error) - Info(ctx context.Context) (system.Info, error) - RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error) + Events(ctx context.Context, options EventsListOptions) EventsResult + Info(ctx context.Context, options InfoOptions) (SystemInfoResult, error) + RegistryLogin(ctx context.Context, auth RegistryLoginOptions) (RegistryLoginResult, error) DiskUsage(ctx context.Context, options DiskUsageOptions) (system.DiskUsage, error) Ping(ctx context.Context, options PingOptions) (PingResult, error) } @@ -191,9 +185,9 @@ type VolumeAPIClient interface { VolumeCreate(ctx context.Context, options VolumeCreateOptions) (VolumeCreateResult, error) VolumeInspect(ctx context.Context, volumeID string, options VolumeInspectOptions) (VolumeInspectResult, error) VolumeList(ctx context.Context, options VolumeListOptions) (VolumeListResult, error) - VolumeRemove(ctx context.Context, volumeID string, options VolumeRemoveOptions) error - VolumesPrune(ctx context.Context, opts VolumePruneOptions) (VolumePruneResult, error) - VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options VolumeUpdateOptions) error + VolumeRemove(ctx context.Context, volumeID string, options VolumeRemoveOptions) (VolumeRemoveResult, error) + VolumesPrune(ctx context.Context, options VolumePruneOptions) (VolumePruneResult, error) + VolumeUpdate(ctx context.Context, volumeID string, options VolumeUpdateOptions) (VolumeUpdateResult, error) } // SecretAPIClient defines API client methods for secrets diff --git a/vendor/github.com/moby/moby/client/container_copy.go b/vendor/github.com/moby/moby/client/container_copy.go index 48bff5d986..f76511246c 100644 --- a/vendor/github.com/moby/moby/client/container_copy.go +++ b/vendor/github.com/moby/moby/client/container_copy.go @@ -14,41 +14,57 @@ import ( "github.com/moby/moby/api/types/container" ) +type ContainerStatPathOptions struct { + Path string +} + +type ContainerStatPathResult struct { + Stat container.PathStat +} + // ContainerStatPath returns stat information about a path inside the container filesystem. -func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (container.PathStat, error) { +func (cli *Client) ContainerStatPath(ctx context.Context, containerID string, options ContainerStatPathOptions) (ContainerStatPathResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.PathStat{}, err + return ContainerStatPathResult{}, err } query := url.Values{} - query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. + query.Set("path", filepath.ToSlash(options.Path)) // Normalize the paths used in the API. resp, err := cli.head(ctx, "/containers/"+containerID+"/archive", query, nil) defer ensureReaderClosed(resp) if err != nil { - return container.PathStat{}, err + return ContainerStatPathResult{}, err } - return getContainerPathStatFromHeader(resp.Header) + stat, err := getContainerPathStatFromHeader(resp.Header) + if err != nil { + return ContainerStatPathResult{}, err + } + return ContainerStatPathResult{Stat: stat}, nil } // CopyToContainerOptions holds information // about files to copy into a container type CopyToContainerOptions struct { + DestinationPath string + Content io.Reader AllowOverwriteDirWithFile bool CopyUIDGID bool } +type CopyToContainerResult struct{} + // CopyToContainer copies content into the container filesystem. // Note that `content` must be a Reader for a TAR archive -func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options CopyToContainerOptions) error { +func (cli *Client) CopyToContainer(ctx context.Context, containerID string, options CopyToContainerOptions) (CopyToContainerResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return err + return CopyToContainerResult{}, err } query := url.Values{} - query.Set("path", filepath.ToSlash(dstPath)) // Normalize the paths used in the API. + query.Set("path", filepath.ToSlash(options.DestinationPath)) // Normalize the paths used in the API. // Do not allow for an existing directory to be overwritten by a non-directory and vice versa. if !options.AllowOverwriteDirWithFile { query.Set("noOverwriteDirNonDir", "true") @@ -58,29 +74,38 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str query.Set("copyUIDGID", "true") } - response, err := cli.putRaw(ctx, "/containers/"+containerID+"/archive", query, content, nil) + response, err := cli.putRaw(ctx, "/containers/"+containerID+"/archive", query, options.Content, nil) defer ensureReaderClosed(response) if err != nil { - return err + return CopyToContainerResult{}, err } - return nil + return CopyToContainerResult{}, nil +} + +type CopyFromContainerOptions struct { + SourcePath string +} + +type CopyFromContainerResult struct { + Content io.ReadCloser + Stat container.PathStat } // CopyFromContainer gets the content from the container and returns it as a Reader // for a TAR archive to manipulate it in the host. It's up to the caller to close the reader. -func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, container.PathStat, error) { +func (cli *Client) CopyFromContainer(ctx context.Context, containerID string, options CopyFromContainerOptions) (CopyFromContainerResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return nil, container.PathStat{}, err + return CopyFromContainerResult{}, err } query := make(url.Values, 1) - query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. + query.Set("path", filepath.ToSlash(options.SourcePath)) // Normalize the paths used in the API. resp, err := cli.get(ctx, "/containers/"+containerID+"/archive", query, nil) if err != nil { - return nil, container.PathStat{}, err + return CopyFromContainerResult{}, err } // In order to get the copy behavior right, we need to know information @@ -91,9 +116,10 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s // can be when copying a file/dir from one location to another file/dir. stat, err := getContainerPathStatFromHeader(resp.Header) if err != nil { - return nil, stat, fmt.Errorf("unable to get resource stat from response: %s", err) + ensureReaderClosed(resp) + return CopyFromContainerResult{Stat: stat}, fmt.Errorf("unable to get resource stat from response: %s", err) } - return resp.Body, stat, err + return CopyFromContainerResult{Content: resp.Body, Stat: stat}, nil } func getContainerPathStatFromHeader(header http.Header) (container.PathStat, error) { diff --git a/vendor/github.com/moby/moby/client/container_export.go b/vendor/github.com/moby/moby/client/container_export.go index 211d92ed75..ca40fe78ad 100644 --- a/vendor/github.com/moby/moby/client/container_export.go +++ b/vendor/github.com/moby/moby/client/container_export.go @@ -4,21 +4,59 @@ import ( "context" "io" "net/url" + "sync" ) +// ContainerExportOptions specifies options for container export operations. +type ContainerExportOptions struct { + // Currently no options are defined for ContainerExport +} + +// ContainerExportResult represents the result of a container export operation. +type ContainerExportResult struct { + rc io.ReadCloser + close func() error +} + // ContainerExport retrieves the raw contents of a container // and returns them as an [io.ReadCloser]. It's up to the caller // to close the stream. -func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) { +func (cli *Client) ContainerExport(ctx context.Context, containerID string, options ContainerExportOptions) (ContainerExportResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return nil, err + return ContainerExportResult{}, err } resp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil) if err != nil { - return nil, err + return ContainerExportResult{}, err } - return resp.Body, nil + return newContainerExportResult(resp.Body), nil +} + +func newContainerExportResult(rc io.ReadCloser) ContainerExportResult { + if rc == nil { + panic("nil io.ReadCloser") + } + return ContainerExportResult{ + rc: rc, + close: sync.OnceValue(rc.Close), + } +} + +// Read implements io.ReadCloser +func (r ContainerExportResult) Read(p []byte) (n int, err error) { + if r.rc == nil { + return 0, io.EOF + } + return r.rc.Read(p) +} + +// Close implements io.ReadCloser +func (r ContainerExportResult) Close() error { + if r.close == nil { + return nil + } + return r.close() } diff --git a/vendor/github.com/moby/moby/client/container_list.go b/vendor/github.com/moby/moby/client/container_list.go index 0b181aafaf..fcd39c4da5 100644 --- a/vendor/github.com/moby/moby/client/container_list.go +++ b/vendor/github.com/moby/moby/client/container_list.go @@ -20,8 +20,12 @@ type ContainerListOptions struct { Filters Filters } +type ContainerListResult struct { + Items []container.Summary +} + // ContainerList returns the list of containers in the docker host. -func (cli *Client) ContainerList(ctx context.Context, options ContainerListOptions) ([]container.Summary, error) { +func (cli *Client) ContainerList(ctx context.Context, options ContainerListOptions) (ContainerListResult, error) { query := url.Values{} if options.All { @@ -49,10 +53,10 @@ func (cli *Client) ContainerList(ctx context.Context, options ContainerListOptio resp, err := cli.get(ctx, "/containers/json", query, nil) defer ensureReaderClosed(resp) if err != nil { - return nil, err + return ContainerListResult{}, err } var containers []container.Summary err = json.NewDecoder(resp.Body).Decode(&containers) - return containers, err + return ContainerListResult{Items: containers}, err } diff --git a/vendor/github.com/moby/moby/client/container_logs.go b/vendor/github.com/moby/moby/client/container_logs.go index 9acd93782a..71c698e9eb 100644 --- a/vendor/github.com/moby/moby/client/container_logs.go +++ b/vendor/github.com/moby/moby/client/container_logs.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/url" + "sync" "time" "github.com/moby/moby/client/internal/timestamp" @@ -22,6 +23,12 @@ type ContainerLogsOptions struct { Details bool } +// ContainerLogsResult is the result of a container logs operation. +type ContainerLogsResult struct { + rc io.ReadCloser + close func() error +} + // ContainerLogs returns the logs generated by a container in an [io.ReadCloser]. // It's up to the caller to close the stream. // @@ -48,10 +55,10 @@ type ContainerLogsOptions 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) ContainerLogs(ctx context.Context, containerID string, options ContainerLogsOptions) (io.ReadCloser, error) { +func (cli *Client) ContainerLogs(ctx context.Context, containerID string, options ContainerLogsOptions) (ContainerLogsResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return nil, err + return ContainerLogsResult{}, err } query := url.Values{} @@ -66,7 +73,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, containerID string, option if options.Since != "" { ts, err := timestamp.GetTimestamp(options.Since, time.Now()) if err != nil { - return nil, fmt.Errorf(`invalid value for "since": %w`, err) + return ContainerLogsResult{}, fmt.Errorf(`invalid value for "since": %w`, err) } query.Set("since", ts) } @@ -74,7 +81,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, containerID string, option if options.Until != "" { ts, err := timestamp.GetTimestamp(options.Until, time.Now()) if err != nil { - return nil, fmt.Errorf(`invalid value for "until": %w`, err) + return ContainerLogsResult{}, fmt.Errorf(`invalid value for "until": %w`, err) } query.Set("until", ts) } @@ -94,7 +101,33 @@ func (cli *Client) ContainerLogs(ctx context.Context, containerID string, option resp, err := cli.get(ctx, "/containers/"+containerID+"/logs", query, nil) if err != nil { - return nil, err + return ContainerLogsResult{}, err } - return resp.Body, nil + return newContainerLogsResult(resp.Body), nil +} + +func newContainerLogsResult(rc io.ReadCloser) ContainerLogsResult { + if rc == nil { + panic("rc cannot be nil") + } + return ContainerLogsResult{ + rc: rc, + close: sync.OnceValue(rc.Close), + } +} + +// Read implements the io.Reader interface. +func (r ContainerLogsResult) Read(p []byte) (n int, err error) { + if r.rc == nil { + return 0, io.EOF + } + return r.rc.Read(p) +} + +// Close closes the underlying reader. +func (r ContainerLogsResult) Close() error { + if r.close == nil { + return nil + } + return r.close() } diff --git a/vendor/github.com/moby/moby/client/container_rename.go b/vendor/github.com/moby/moby/client/container_rename.go index 9eba310d5a..6ce1500080 100644 --- a/vendor/github.com/moby/moby/client/container_rename.go +++ b/vendor/github.com/moby/moby/client/container_rename.go @@ -5,16 +5,26 @@ import ( "net/url" ) +// ContainerRenameOptions represents the options for renaming a container. +type ContainerRenameOptions struct { + NewName string +} + +// ContainerRenameResult represents the result of a container rename operation. +type ContainerRenameResult struct { + // This struct can be expanded in the future if needed +} + // ContainerRename changes the name of a given container. -func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error { +func (cli *Client) ContainerRename(ctx context.Context, containerID string, options ContainerRenameOptions) (ContainerRenameResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return err + return ContainerRenameResult{}, err } query := url.Values{} - query.Set("name", newContainerName) + query.Set("name", options.NewName) resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil) defer ensureReaderClosed(resp) - return err + return ContainerRenameResult{}, err } diff --git a/vendor/github.com/moby/moby/client/container_top.go b/vendor/github.com/moby/moby/client/container_top.go index 96b7e87f3d..dc0af8ae48 100644 --- a/vendor/github.com/moby/moby/client/container_top.go +++ b/vendor/github.com/moby/moby/client/container_top.go @@ -9,25 +9,36 @@ import ( "github.com/moby/moby/api/types/container" ) +// ContainerTopOptions defines options for container top operations. +type ContainerTopOptions struct { + Arguments []string +} + +// ContainerTopResult represents the result of a ContainerTop operation. +type ContainerTopResult struct { + Processes [][]string + Titles []string +} + // ContainerTop shows process information from within a container. -func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (container.TopResponse, error) { +func (cli *Client) ContainerTop(ctx context.Context, containerID string, options ContainerTopOptions) (ContainerTopResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.TopResponse{}, err + return ContainerTopResult{}, err } query := url.Values{} - if len(arguments) > 0 { - query.Set("ps_args", strings.Join(arguments, " ")) + if len(options.Arguments) > 0 { + query.Set("ps_args", strings.Join(options.Arguments, " ")) } resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) defer ensureReaderClosed(resp) if err != nil { - return container.TopResponse{}, err + return ContainerTopResult{}, err } var response container.TopResponse err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerTopResult{Processes: response.Processes, Titles: response.Titles}, err } diff --git a/vendor/github.com/moby/moby/client/container_unpause.go b/vendor/github.com/moby/moby/client/container_unpause.go index 4c37c774dd..627d60c960 100644 --- a/vendor/github.com/moby/moby/client/container_unpause.go +++ b/vendor/github.com/moby/moby/client/container_unpause.go @@ -2,27 +2,27 @@ package client import "context" -// ContainerUnPauseOptions holds options for [Client.ContainerUnpause]. -type ContainerUnPauseOptions struct { +// ContainerUnpauseOptions holds options for [Client.ContainerUnpause]. +type ContainerUnpauseOptions struct { // Add future optional parameters here. } -// ContainerUnPauseResult holds the result of [Client.ContainerUnpause], -type ContainerUnPauseResult struct { +// ContainerUnpauseResult holds the result of [Client.ContainerUnpause], +type ContainerUnpauseResult struct { // Add future fields here. } // ContainerUnpause resumes the process execution within a container. -func (cli *Client) ContainerUnpause(ctx context.Context, containerID string, options ContainerUnPauseOptions) (ContainerUnPauseResult, error) { +func (cli *Client) ContainerUnpause(ctx context.Context, containerID string, options ContainerUnpauseOptions) (ContainerUnpauseResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return ContainerUnPauseResult{}, err + return ContainerUnpauseResult{}, err } resp, err := cli.post(ctx, "/containers/"+containerID+"/unpause", nil, nil, nil) defer ensureReaderClosed(resp) if err != nil { - return ContainerUnPauseResult{}, err + return ContainerUnpauseResult{}, err } - return ContainerUnPauseResult{}, nil + return ContainerUnpauseResult{}, nil } diff --git a/vendor/github.com/moby/moby/client/container_update.go b/vendor/github.com/moby/moby/client/container_update.go index fc524b1c91..a1d4d249a9 100644 --- a/vendor/github.com/moby/moby/client/container_update.go +++ b/vendor/github.com/moby/moby/client/container_update.go @@ -7,20 +7,40 @@ import ( "github.com/moby/moby/api/types/container" ) +// ContainerUpdateOptions holds options for [Client.ContainerUpdate]. +type ContainerUpdateOptions struct { + Resources *container.Resources + RestartPolicy *container.RestartPolicy +} + +// ContainerUpdateResult is the result from updating a container. +type ContainerUpdateResult struct { + // Warnings encountered when updating the container. + Warnings []string +} + // ContainerUpdate updates the resources of a container. -func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.UpdateResponse, error) { +func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, options ContainerUpdateOptions) (ContainerUpdateResult, error) { containerID, err := trimID("container", containerID) if err != nil { - return container.UpdateResponse{}, err + return ContainerUpdateResult{}, err + } + + updateConfig := container.UpdateConfig{} + if options.Resources != nil { + updateConfig.Resources = *options.Resources + } + if options.RestartPolicy != nil { + updateConfig.RestartPolicy = *options.RestartPolicy } resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) defer ensureReaderClosed(resp) if err != nil { - return container.UpdateResponse{}, err + return ContainerUpdateResult{}, err } var response container.UpdateResponse err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return ContainerUpdateResult{Warnings: response.Warnings}, err } diff --git a/vendor/github.com/moby/moby/client/container_wait.go b/vendor/github.com/moby/moby/client/container_wait.go index 4267af92ee..6f71ed0518 100644 --- a/vendor/github.com/moby/moby/client/container_wait.go +++ b/vendor/github.com/moby/moby/client/container_wait.go @@ -13,43 +13,51 @@ import ( const containerWaitErrorMsgLimit = 2 * 1024 /* Max: 2KiB */ +// ContainerWaitOptions holds options for [Client.ContainerWait]. +type ContainerWaitOptions struct { + Condition container.WaitCondition +} + +// ContainerWaitResult defines the result from the [Client.ContainerWait] method. +type ContainerWaitResult struct { + Result <-chan container.WaitResponse + Error <-chan error +} + // ContainerWait waits until the specified container is in a certain state -// indicated by the given condition, either "not-running" ([container.WaitConditionNotRunning]) -// (default), "next-exit" ([container.WaitConditionNextExit]), or "removed". -// ([container.WaitConditionRemoved]). +// indicated by the given condition, either; // -// If this client's API version is before 1.30, "condition" is ignored and -// ContainerWait returns immediately with the two channels, as the server -// waits as if the condition were "not-running". +// - "not-running" ([container.WaitConditionNotRunning]) (default) +// - "next-exit" ([container.WaitConditionNextExit]) +// - "removed" ([container.WaitConditionRemoved]) // -// If this client's API version is at least 1.30, ContainerWait blocks until -// the request has been acknowledged by the server (with a response header), -// then returns two channels on which the caller can wait for the exit status -// of the container or an error if there was a problem either beginning the -// wait request or in getting the response. This allows the caller to -// synchronize ContainerWait with other calls, such as specifying a -// "next-exit" condition ([container.WaitConditionNextExit]) before -// issuing a [Client.ContainerStart] request. -func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) { +// ContainerWait blocks until the request has been acknowledged by the server +// (with a response header), then returns two channels on which the caller can +// wait for the exit status of the container or an error if there was a problem +// either beginning the wait request or in getting the response. This allows the +// caller to synchronize ContainerWait with other calls, such as specifying a +// "next-exit" condition ([container.WaitConditionNextExit]) before issuing a +// [Client.ContainerStart] request. +func (cli *Client) ContainerWait(ctx context.Context, containerID string, options ContainerWaitOptions) ContainerWaitResult { resultC := make(chan container.WaitResponse) errC := make(chan error, 1) containerID, err := trimID("container", containerID) if err != nil { errC <- err - return resultC, errC + return ContainerWaitResult{Result: resultC, Error: errC} } query := url.Values{} - if condition != "" { - query.Set("condition", string(condition)) + if options.Condition != "" { + query.Set("condition", string(options.Condition)) } resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", query, nil, nil) if err != nil { defer ensureReaderClosed(resp) errC <- err - return resultC, errC + return ContainerWaitResult{Result: resultC, Error: errC} } go func() { @@ -80,31 +88,5 @@ func (cli *Client) ContainerWait(ctx context.Context, containerID string, condit resultC <- res }() - return resultC, errC -} - -// legacyContainerWait returns immediately and doesn't have an option to wait -// until the container is removed. -func (cli *Client) legacyContainerWait(ctx context.Context, containerID string) (<-chan container.WaitResponse, <-chan error) { - resultC := make(chan container.WaitResponse) - errC := make(chan error) - - go func() { - resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", nil, nil, nil) - if err != nil { - errC <- err - return - } - defer ensureReaderClosed(resp) - - var res container.WaitResponse - if err := json.NewDecoder(resp.Body).Decode(&res); err != nil { - errC <- err - return - } - - resultC <- res - }() - - return resultC, errC + return ContainerWaitResult{Result: resultC, Error: errC} } diff --git a/vendor/github.com/moby/moby/client/errors.go b/vendor/github.com/moby/moby/client/errors.go index 4980d7cadc..9fbfa7666e 100644 --- a/vendor/github.com/moby/moby/client/errors.go +++ b/vendor/github.com/moby/moby/client/errors.go @@ -53,12 +53,12 @@ func (e objectNotFoundError) Error() string { return fmt.Sprintf("Error: No such %s: %s", e.object, e.id) } -// NewVersionError returns an error if the APIVersion required is less than the +// requiresVersion returns an error if the APIVersion required is less than the // current supported version. // // It performs API-version negotiation if the Client is configured with this // option, otherwise it assumes the latest API version is used. -func (cli *Client) NewVersionError(ctx context.Context, APIrequired, feature string) error { +func (cli *Client) requiresVersion(ctx context.Context, apiRequired, feature string) error { // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. // @@ -67,8 +67,8 @@ func (cli *Client) NewVersionError(ctx context.Context, APIrequired, feature str if err := cli.checkVersion(ctx); err != nil { return err } - if cli.version != "" && versions.LessThan(cli.version, APIrequired) { - return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version) + if cli.version != "" && versions.LessThan(cli.version, apiRequired) { + return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, apiRequired, cli.version) } return nil } diff --git a/vendor/github.com/moby/moby/client/image_history.go b/vendor/github.com/moby/moby/client/image_history.go index 9bf627d4c7..8618f1553e 100644 --- a/vendor/github.com/moby/moby/client/image_history.go +++ b/vendor/github.com/moby/moby/client/image_history.go @@ -32,7 +32,7 @@ func (cli *Client) ImageHistory(ctx context.Context, imageID string, historyOpts } if opts.apiOptions.Platform != nil { - if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { + if err := cli.requiresVersion(ctx, "1.48", "platform"); err != nil { return ImageHistoryResult{}, err } diff --git a/vendor/github.com/moby/moby/client/image_inspect.go b/vendor/github.com/moby/moby/client/image_inspect.go index b31ce14282..635931fd03 100644 --- a/vendor/github.com/moby/moby/client/image_inspect.go +++ b/vendor/github.com/moby/moby/client/image_inspect.go @@ -24,14 +24,14 @@ func (cli *Client) ImageInspect(ctx context.Context, imageID string, inspectOpts query := url.Values{} if opts.apiOptions.Manifests { - if err := cli.NewVersionError(ctx, "1.48", "manifests"); err != nil { + if err := cli.requiresVersion(ctx, "1.48", "manifests"); err != nil { return ImageInspectResult{}, err } query.Set("manifests", "1") } if opts.apiOptions.Platform != nil { - if err := cli.NewVersionError(ctx, "1.49", "platform"); err != nil { + if err := cli.requiresVersion(ctx, "1.49", "platform"); err != nil { return ImageInspectResult{}, err } platform, err := encodePlatform(opts.apiOptions.Platform) diff --git a/vendor/github.com/moby/moby/client/image_load.go b/vendor/github.com/moby/moby/client/image_load.go index fab3098460..2be1869297 100644 --- a/vendor/github.com/moby/moby/client/image_load.go +++ b/vendor/github.com/moby/moby/client/image_load.go @@ -28,7 +28,7 @@ func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, loadOpts ...I query.Set("quiet", "1") } if len(opts.apiOptions.Platforms) > 0 { - if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { + if err := cli.requiresVersion(ctx, "1.48", "platform"); err != nil { return ImageLoadResult{}, err } diff --git a/vendor/github.com/moby/moby/client/image_push.go b/vendor/github.com/moby/moby/client/image_push.go index b50e1dd3f3..66114d6158 100644 --- a/vendor/github.com/moby/moby/client/image_push.go +++ b/vendor/github.com/moby/moby/client/image_push.go @@ -50,7 +50,7 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options ImagePus } if options.Platform != nil { - if err := cli.NewVersionError(ctx, "1.46", "platform"); err != nil { + if err := cli.requiresVersion(ctx, "1.46", "platform"); err != nil { return nil, err } diff --git a/vendor/github.com/moby/moby/client/image_save.go b/vendor/github.com/moby/moby/client/image_save.go index 6ea4a8ec2f..5be9864186 100644 --- a/vendor/github.com/moby/moby/client/image_save.go +++ b/vendor/github.com/moby/moby/client/image_save.go @@ -24,7 +24,7 @@ func (cli *Client) ImageSave(ctx context.Context, imageIDs []string, saveOpts .. } if len(opts.apiOptions.Platforms) > 0 { - if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { + if err := cli.requiresVersion(ctx, "1.48", "platform"); err != nil { return ImageSaveResult{}, err } p, err := encodePlatforms(opts.apiOptions.Platforms...) diff --git a/vendor/github.com/moby/moby/client/login.go b/vendor/github.com/moby/moby/client/login.go index 9cb365338d..6974ec22ce 100644 --- a/vendor/github.com/moby/moby/client/login.go +++ b/vendor/github.com/moby/moby/client/login.go @@ -8,17 +8,38 @@ import ( "github.com/moby/moby/api/types/registry" ) +type RegistryLoginOptions struct { + Username string + Password string + ServerAddress string + IdentityToken string + RegistryToken string +} + +// RegistryLoginResult holds the result of a RegistryLogin query. +type RegistryLoginResult struct { + Auth registry.AuthenticateOKBody +} + // RegistryLogin authenticates the docker server with a given docker registry. // It returns unauthorizedError when the authentication fails. -func (cli *Client) RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error) { +func (cli *Client) RegistryLogin(ctx context.Context, options RegistryLoginOptions) (RegistryLoginResult, error) { + auth := registry.AuthConfig{ + Username: options.Username, + Password: options.Password, + ServerAddress: options.ServerAddress, + IdentityToken: options.IdentityToken, + RegistryToken: options.RegistryToken, + } + resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil) defer ensureReaderClosed(resp) if err != nil { - return registry.AuthenticateOKBody{}, err + return RegistryLoginResult{}, err } var response registry.AuthenticateOKBody err = json.NewDecoder(resp.Body).Decode(&response) - return response, err + return RegistryLoginResult{Auth: response}, err } diff --git a/vendor/github.com/moby/moby/client/network_connect.go b/vendor/github.com/moby/moby/client/network_connect.go index 985b0f6fa3..40db955a90 100644 --- a/vendor/github.com/moby/moby/client/network_connect.go +++ b/vendor/github.com/moby/moby/client/network_connect.go @@ -6,23 +6,35 @@ import ( "github.com/moby/moby/api/types/network" ) +// NetworkConnectOptions represents the data to be used to connect a container to the +// network. +type NetworkConnectOptions struct { + Container string + EndpointConfig *network.EndpointSettings +} + +// NetworkConnectResult represents the result of a NetworkConnect operation. +type NetworkConnectResult struct { + // Currently empty; placeholder for future fields. +} + // NetworkConnect connects a container to an existent network in the docker host. -func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error { +func (cli *Client) NetworkConnect(ctx context.Context, networkID string, options NetworkConnectOptions) (NetworkConnectResult, error) { networkID, err := trimID("network", networkID) if err != nil { - return err + return NetworkConnectResult{}, err } - containerID, err = trimID("container", containerID) + containerID, err := trimID("container", options.Container) if err != nil { - return err + return NetworkConnectResult{}, err } - nc := NetworkConnectOptions{ + nc := network.ConnectRequest{ Container: containerID, - EndpointConfig: config, + EndpointConfig: options.EndpointConfig, } resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil) defer ensureReaderClosed(resp) - return err + return NetworkConnectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/network_connect_opts.go b/vendor/github.com/moby/moby/client/network_connect_opts.go deleted file mode 100644 index 13816dfd73..0000000000 --- a/vendor/github.com/moby/moby/client/network_connect_opts.go +++ /dev/null @@ -1,10 +0,0 @@ -package client - -import "github.com/moby/moby/api/types/network" - -// NetworkConnectOptions represents the data to be used to connect a container to the -// network. -type NetworkConnectOptions struct { - Container string - EndpointConfig *network.EndpointSettings `json:",omitempty"` -} diff --git a/vendor/github.com/moby/moby/client/network_disconnect.go b/vendor/github.com/moby/moby/client/network_disconnect.go index 4931f536a7..64a1796b8d 100644 --- a/vendor/github.com/moby/moby/client/network_disconnect.go +++ b/vendor/github.com/moby/moby/client/network_disconnect.go @@ -2,25 +2,39 @@ package client import ( "context" + + "github.com/moby/moby/api/types/network" ) +// NetworkDisconnectOptions represents the data to be used to disconnect a container +// from the network. +type NetworkDisconnectOptions struct { + Container string + Force bool +} + +// NetworkDisconnectResult represents the result of a NetworkDisconnect operation. +type NetworkDisconnectResult struct { + // Currently empty; placeholder for future fields. +} + // NetworkDisconnect disconnects a container from an existent network in the docker host. -func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error { +func (cli *Client) NetworkDisconnect(ctx context.Context, networkID string, options NetworkDisconnectOptions) (NetworkDisconnectResult, error) { networkID, err := trimID("network", networkID) if err != nil { - return err + return NetworkDisconnectResult{}, err } - containerID, err = trimID("container", containerID) + containerID, err := trimID("container", options.Container) if err != nil { - return err + return NetworkDisconnectResult{}, err } - nd := NetworkDisconnectOptions{ + req := network.DisconnectRequest{ Container: containerID, - Force: force, + Force: options.Force, } - resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, nd, nil) + resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, req, nil) defer ensureReaderClosed(resp) - return err + return NetworkDisconnectResult{}, err } diff --git a/vendor/github.com/moby/moby/client/network_disconnect_opts.go b/vendor/github.com/moby/moby/client/network_disconnect_opts.go deleted file mode 100644 index 9399272856..0000000000 --- a/vendor/github.com/moby/moby/client/network_disconnect_opts.go +++ /dev/null @@ -1,8 +0,0 @@ -package client - -// NetworkDisconnectOptions represents the data to be used to disconnect a container -// from the network. -type NetworkDisconnectOptions struct { - Container string - Force bool -} diff --git a/vendor/github.com/moby/moby/client/network_remove.go b/vendor/github.com/moby/moby/client/network_remove.go index 9b164d3eae..2bceb0d934 100644 --- a/vendor/github.com/moby/moby/client/network_remove.go +++ b/vendor/github.com/moby/moby/client/network_remove.go @@ -1,14 +1,26 @@ package client -import "context" +import ( + "context" +) + +// NetworkRemoveOptions specifies options for removing a network. +type NetworkRemoveOptions struct { + // No options currently; placeholder for future use. +} + +// NetworkRemoveResult represents the result of a network removal operation. +type NetworkRemoveResult struct { + // No fields currently; placeholder for future use. +} // NetworkRemove removes an existent network from the docker host. -func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { +func (cli *Client) NetworkRemove(ctx context.Context, networkID string, options NetworkRemoveOptions) (NetworkRemoveResult, error) { networkID, err := trimID("network", networkID) if err != nil { - return err + return NetworkRemoveResult{}, err } resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) defer ensureReaderClosed(resp) - return err + return NetworkRemoveResult{}, err } diff --git a/vendor/github.com/moby/moby/client/ping.go b/vendor/github.com/moby/moby/client/ping.go index 80359fb457..15c54faa0c 100644 --- a/vendor/github.com/moby/moby/client/ping.go +++ b/vendor/github.com/moby/moby/client/ping.go @@ -12,7 +12,29 @@ import ( // PingOptions holds options for [client.Ping]. type PingOptions struct { - // Add future optional parameters here + // NegotiateAPIVersion queries the API and updates the version to match the API + // version. NegotiateAPIVersion downgrades the client's API version to match the + // APIVersion if the ping version is lower than the default version. If the API + // version reported by the server is higher than the maximum version supported + // by the client, it uses the client's maximum version. + // + // If a manual override is in place, either through the "DOCKER_API_VERSION" + // ([EnvOverrideAPIVersion]) environment variable, or if the client is initialized + // with a fixed version ([WithVersion]), no negotiation is performed. + // + // If the API server's ping response does not contain an API version, or if the + // client did not get a successful ping response, it assumes it is connected with + // an old daemon that does not support API version negotiation, in which case it + // downgrades to the lowest supported API version. + NegotiateAPIVersion bool + + // ForceNegotiate forces the client to re-negotiate the API version, even if + // API-version negotiation already happened. This option cannot be + // used if the client is configured with a fixed version using (using + // [WithVersion] or [WithVersionFromEnv]). + // + // This option has no effect if NegotiateAPIVersion is not set. + ForceNegotiate bool } // PingResult holds the result of a [Client.Ping] API call. @@ -50,6 +72,30 @@ type SwarmStatus struct { // for other non-success status codes, failing to connect to the API, or failing // to parse the API response. func (cli *Client) Ping(ctx context.Context, options PingOptions) (PingResult, error) { + if cli.manualOverride { + return cli.ping(ctx) + } + if !options.NegotiateAPIVersion && !cli.negotiateVersion { + return cli.ping(ctx) + } + + // Ensure exclusive write access to version and negotiated fields + cli.negotiateLock.Lock() + defer cli.negotiateLock.Unlock() + + ping, err := cli.ping(ctx) + if err != nil { + return cli.ping(ctx) + } + + if cli.negotiated.Load() && !options.ForceNegotiate { + return ping, nil + } + + return ping, cli.negotiateAPIVersion(ping.APIVersion) +} + +func (cli *Client) ping(ctx context.Context) (PingResult, error) { // Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest() // because ping requests are used during API version negotiation, so we want // to hit the non-versioned /_ping endpoint, not /v1.xx/_ping diff --git a/vendor/github.com/moby/moby/client/system_events.go b/vendor/github.com/moby/moby/client/system_events.go index 598c2e25d3..748e012086 100644 --- a/vendor/github.com/moby/moby/client/system_events.go +++ b/vendor/github.com/moby/moby/client/system_events.go @@ -19,11 +19,17 @@ type EventsListOptions struct { Filters Filters } +// EventsResult holds the result of an Events query. +type EventsResult struct { + Messages <-chan events.Message + Err <-chan error +} + // Events returns a stream of events in the daemon. It's up to the caller to close the stream // by cancelling the context. Once the stream has been completely read an [io.EOF] error is // sent over the error channel. If an error is sent, all processing is stopped. It's up // to the caller to reopen the stream in the event of an error by reinvoking this method. -func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-chan events.Message, <-chan error) { +func (cli *Client) Events(ctx context.Context, options EventsListOptions) EventsResult { messages := make(chan events.Message) errs := make(chan error, 1) @@ -76,7 +82,10 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-cha }() <-started - return messages, errs + return EventsResult{ + Messages: messages, + Err: errs, + } } func buildEventsQueryParams(options EventsListOptions) (url.Values, error) { diff --git a/vendor/github.com/moby/moby/client/system_info.go b/vendor/github.com/moby/moby/client/system_info.go index 865cd35eee..4c0a2238e1 100644 --- a/vendor/github.com/moby/moby/client/system_info.go +++ b/vendor/github.com/moby/moby/client/system_info.go @@ -9,18 +9,26 @@ import ( "github.com/moby/moby/api/types/system" ) +type InfoOptions struct { + // No options currently; placeholder for future use +} + +type SystemInfoResult struct { + Info system.Info +} + // Info returns information about the docker server. -func (cli *Client) Info(ctx context.Context) (system.Info, error) { - var info system.Info +func (cli *Client) Info(ctx context.Context, options InfoOptions) (SystemInfoResult, error) { resp, err := cli.get(ctx, "/info", url.Values{}, nil) defer ensureReaderClosed(resp) if err != nil { - return info, err + return SystemInfoResult{}, err } + var info system.Info if err := json.NewDecoder(resp.Body).Decode(&info); err != nil { - return info, fmt.Errorf("Error reading remote info: %v", err) + return SystemInfoResult{}, fmt.Errorf("Error reading remote info: %v", err) } - return info, nil + return SystemInfoResult{Info: info}, nil } diff --git a/vendor/github.com/moby/moby/client/volume_prune.go b/vendor/github.com/moby/moby/client/volume_prune.go index 3c000a657c..5487762793 100644 --- a/vendor/github.com/moby/moby/client/volume_prune.go +++ b/vendor/github.com/moby/moby/client/volume_prune.go @@ -26,19 +26,19 @@ type VolumePruneResult struct { } // VolumesPrune requests the daemon to delete unused data -func (cli *Client) VolumesPrune(ctx context.Context, opts VolumePruneOptions) (VolumePruneResult, error) { - if opts.All { - if _, ok := opts.Filters["all"]; ok { +func (cli *Client) VolumesPrune(ctx context.Context, options VolumePruneOptions) (VolumePruneResult, error) { + if options.All { + if _, ok := options.Filters["all"]; ok { return VolumePruneResult{}, errdefs.ErrInvalidArgument.WithMessage(`conflicting options: cannot specify both "all" and "all" filter`) } - if opts.Filters == nil { - opts.Filters = Filters{} + if options.Filters == nil { + options.Filters = Filters{} } - opts.Filters.Add("all", "true") + options.Filters.Add("all", "true") } query := url.Values{} - opts.Filters.updateURLValues(query) + options.Filters.updateURLValues(query) resp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) defer ensureReaderClosed(resp) @@ -48,7 +48,7 @@ func (cli *Client) VolumesPrune(ctx context.Context, opts VolumePruneOptions) (V var report volume.PruneReport if err := json.NewDecoder(resp.Body).Decode(&report); err != nil { - return VolumePruneResult{}, fmt.Errorf("Error retrieving volume prune report: %v", err) + return VolumePruneResult{}, fmt.Errorf("error retrieving volume prune report: %v", err) } return VolumePruneResult{Report: report}, nil diff --git a/vendor/github.com/moby/moby/client/volume_remove.go b/vendor/github.com/moby/moby/client/volume_remove.go index 1df9a0ca89..0449e08d4a 100644 --- a/vendor/github.com/moby/moby/client/volume_remove.go +++ b/vendor/github.com/moby/moby/client/volume_remove.go @@ -5,17 +5,22 @@ import ( "net/url" ) -// VolumeRemoveOptions holds optional parameters for volume removal. +// VolumeRemoveOptions holds options for [Client.VolumeRemove]. type VolumeRemoveOptions struct { // Force the removal of the volume Force bool } +// VolumeRemoveResult holds the result of [Client.VolumeRemove], +type VolumeRemoveResult struct { + // Add future fields here. +} + // VolumeRemove removes a volume from the docker host. -func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, options VolumeRemoveOptions) error { +func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, options VolumeRemoveOptions) (VolumeRemoveResult, error) { volumeID, err := trimID("volume", volumeID) if err != nil { - return err + return VolumeRemoveResult{}, err } query := url.Values{} @@ -24,5 +29,8 @@ func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, options Vo } resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil) defer ensureReaderClosed(resp) - return err + if err != nil { + return VolumeRemoveResult{}, err + } + return VolumeRemoveResult{}, nil } diff --git a/vendor/github.com/moby/moby/client/volume_update.go b/vendor/github.com/moby/moby/client/volume_update.go index 20b0f34ea0..5aa2a0aa17 100644 --- a/vendor/github.com/moby/moby/client/volume_update.go +++ b/vendor/github.com/moby/moby/client/volume_update.go @@ -8,23 +8,33 @@ import ( "github.com/moby/moby/api/types/volume" ) +// VolumeUpdateOptions holds options for [Client.VolumeUpdate]. type VolumeUpdateOptions struct { + Version swarm.Version // Spec is the ClusterVolumeSpec to update the volume to. Spec *volume.ClusterVolumeSpec `json:"Spec,omitempty"` } +// VolumeUpdateResult holds the result of [Client.VolumeUpdate], +type VolumeUpdateResult struct { + // Add future fields here. +} + // VolumeUpdate updates a volume. This only works for Cluster Volumes, and // only some fields can be updated. -func (cli *Client) VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options VolumeUpdateOptions) error { +func (cli *Client) VolumeUpdate(ctx context.Context, volumeID string, options VolumeUpdateOptions) (VolumeUpdateResult, error) { volumeID, err := trimID("volume", volumeID) if err != nil { - return err + return VolumeUpdateResult{}, err } query := url.Values{} - query.Set("version", version.String()) + query.Set("version", options.Version.String()) resp, err := cli.put(ctx, "/volumes/"+volumeID, query, options, nil) defer ensureReaderClosed(resp) - return err + if err != nil { + return VolumeUpdateResult{}, err + } + return VolumeUpdateResult{}, nil } diff --git a/vendor/modules.txt b/vendor/modules.txt index 569dfb4496..8c552ca01c 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.20251028144225-90109a373da9 +# github.com/moby/moby/api v1.52.0-beta.2.0.20251029165853-ef17deb3a0fb ## explicit; go 1.23.0 github.com/moby/moby/api/pkg/authconfig github.com/moby/moby/api/pkg/stdcopy @@ -190,7 +190,7 @@ 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/volume -# github.com/moby/moby/client v0.1.0-beta.2.0.20251028144225-90109a373da9 +# github.com/moby/moby/client v0.1.0-beta.2.0.20251029165853-ef17deb3a0fb ## explicit; go 1.23.0 github.com/moby/moby/client github.com/moby/moby/client/internal