mirror of
https://github.com/docker/cli.git
synced 2026-01-06 05:41:44 +03:00
Merge pull request #6586 from thaJeztah/bump_modules
vendor: github.com/moby/moby/api, moby/moby/client master
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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...)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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=",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
20
vendor/github.com/moby/moby/api/types/network/connect_request.go
generated
vendored
Normal file
20
vendor/github.com/moby/moby/api/types/network/connect_request.go
generated
vendored
Normal file
@@ -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"`
|
||||
}
|
||||
21
vendor/github.com/moby/moby/api/types/network/disconnect_request.go
generated
vendored
Normal file
21
vendor/github.com/moby/moby/api/types/network/disconnect_request.go
generated
vendored
Normal file
@@ -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"`
|
||||
}
|
||||
75
vendor/github.com/moby/moby/client/client.go
generated
vendored
75
vendor/github.com/moby/moby/client/client.go
generated
vendored
@@ -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
|
||||
|
||||
46
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
46
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
@@ -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
|
||||
|
||||
60
vendor/github.com/moby/moby/client/container_copy.go
generated
vendored
60
vendor/github.com/moby/moby/client/container_copy.go
generated
vendored
@@ -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) {
|
||||
|
||||
46
vendor/github.com/moby/moby/client/container_export.go
generated
vendored
46
vendor/github.com/moby/moby/client/container_export.go
generated
vendored
@@ -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()
|
||||
}
|
||||
|
||||
10
vendor/github.com/moby/moby/client/container_list.go
generated
vendored
10
vendor/github.com/moby/moby/client/container_list.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
45
vendor/github.com/moby/moby/client/container_logs.go
generated
vendored
45
vendor/github.com/moby/moby/client/container_logs.go
generated
vendored
@@ -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()
|
||||
}
|
||||
|
||||
18
vendor/github.com/moby/moby/client/container_rename.go
generated
vendored
18
vendor/github.com/moby/moby/client/container_rename.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
23
vendor/github.com/moby/moby/client/container_top.go
generated
vendored
23
vendor/github.com/moby/moby/client/container_top.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
16
vendor/github.com/moby/moby/client/container_unpause.go
generated
vendored
16
vendor/github.com/moby/moby/client/container_unpause.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
28
vendor/github.com/moby/moby/client/container_update.go
generated
vendored
28
vendor/github.com/moby/moby/client/container_update.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
74
vendor/github.com/moby/moby/client/container_wait.go
generated
vendored
74
vendor/github.com/moby/moby/client/container_wait.go
generated
vendored
@@ -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}
|
||||
}
|
||||
|
||||
8
vendor/github.com/moby/moby/client/errors.go
generated
vendored
8
vendor/github.com/moby/moby/client/errors.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_history.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_history.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
4
vendor/github.com/moby/moby/client/image_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/image_inspect.go
generated
vendored
@@ -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)
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_load.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_load.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_push.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_push.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_save.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_save.go
generated
vendored
@@ -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...)
|
||||
|
||||
27
vendor/github.com/moby/moby/client/login.go
generated
vendored
27
vendor/github.com/moby/moby/client/login.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
26
vendor/github.com/moby/moby/client/network_connect.go
generated
vendored
26
vendor/github.com/moby/moby/client/network_connect.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
10
vendor/github.com/moby/moby/client/network_connect_opts.go
generated
vendored
10
vendor/github.com/moby/moby/client/network_connect_opts.go
generated
vendored
@@ -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"`
|
||||
}
|
||||
30
vendor/github.com/moby/moby/client/network_disconnect.go
generated
vendored
30
vendor/github.com/moby/moby/client/network_disconnect.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
8
vendor/github.com/moby/moby/client/network_disconnect_opts.go
generated
vendored
8
vendor/github.com/moby/moby/client/network_disconnect_opts.go
generated
vendored
@@ -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
|
||||
}
|
||||
20
vendor/github.com/moby/moby/client/network_remove.go
generated
vendored
20
vendor/github.com/moby/moby/client/network_remove.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
48
vendor/github.com/moby/moby/client/ping.go
generated
vendored
48
vendor/github.com/moby/moby/client/ping.go
generated
vendored
@@ -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
|
||||
|
||||
13
vendor/github.com/moby/moby/client/system_events.go
generated
vendored
13
vendor/github.com/moby/moby/client/system_events.go
generated
vendored
@@ -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) {
|
||||
|
||||
18
vendor/github.com/moby/moby/client/system_info.go
generated
vendored
18
vendor/github.com/moby/moby/client/system_info.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
16
vendor/github.com/moby/moby/client/volume_prune.go
generated
vendored
16
vendor/github.com/moby/moby/client/volume_prune.go
generated
vendored
@@ -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
|
||||
|
||||
16
vendor/github.com/moby/moby/client/volume_remove.go
generated
vendored
16
vendor/github.com/moby/moby/client/volume_remove.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
18
vendor/github.com/moby/moby/client/volume_update.go
generated
vendored
18
vendor/github.com/moby/moby/client/volume_update.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user