vendor: github.com/moby/moby/api, moby/moby/client master
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
@ -115,7 +115,7 @@ func VolumeNames(dockerCLI APIClientProvider) cobra.CompletionFunc {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
var names []string
|
||||
for _, vol := range res.Items.Volumes {
|
||||
for _, vol := range res.Items {
|
||||
names = append(names, vol.Name)
|
||||
}
|
||||
return names, cobra.ShellCompDirectiveNoFileComp
|
||||
|
||||
@ -310,7 +310,7 @@ func TestCompletePlatforms(t *testing.T) {
|
||||
func TestCompleteVolumeNames(t *testing.T) {
|
||||
tests := []struct {
|
||||
doc string
|
||||
volumes []*volume.Volume
|
||||
volumes []volume.Volume
|
||||
expOut []string
|
||||
expDirective cobra.ShellCompDirective
|
||||
}{
|
||||
@ -320,7 +320,7 @@ func TestCompleteVolumeNames(t *testing.T) {
|
||||
},
|
||||
{
|
||||
doc: "with results",
|
||||
volumes: []*volume.Volume{
|
||||
volumes: []volume.Volume{
|
||||
{Name: "volume-c"},
|
||||
{Name: "volume-b"},
|
||||
{Name: "volume-a"},
|
||||
@ -341,7 +341,7 @@ func TestCompleteVolumeNames(t *testing.T) {
|
||||
if tc.expDirective == cobra.ShellCompDirectiveError {
|
||||
return client.VolumeListResult{}, errors.New("some error occurred")
|
||||
}
|
||||
return client.VolumeListResult{Items: volume.ListResponse{Volumes: tc.volumes}}, nil
|
||||
return client.VolumeListResult{Items: tc.volumes}, nil
|
||||
},
|
||||
}})
|
||||
|
||||
|
||||
@ -114,11 +114,11 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o
|
||||
defer signal.StopCatch(sigc)
|
||||
}
|
||||
|
||||
resp, errAttach := apiClient.ContainerAttach(ctx, containerID, options)
|
||||
if errAttach != nil {
|
||||
return errAttach
|
||||
res, err := apiClient.ContainerAttach(ctx, containerID, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Close()
|
||||
defer res.HijackedResponse.Close()
|
||||
|
||||
// If use docker attach command to attach to a stop container, it will return
|
||||
// "You cannot attach to a stopped container" error, it's ok, but when
|
||||
@ -142,7 +142,7 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o
|
||||
inputStream: in,
|
||||
outputStream: dockerCLI.Out(),
|
||||
errorStream: dockerCLI.Err(),
|
||||
resp: resp,
|
||||
resp: res.HijackedResponse,
|
||||
tty: c.Config.Tty,
|
||||
detachKeys: options.DetachKeys,
|
||||
}
|
||||
|
||||
@ -5,22 +5,16 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
"github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/client"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type fakeClient struct {
|
||||
client.Client
|
||||
inspectFunc func(string) (container.InspectResponse, error)
|
||||
execInspectFunc func(execID string) (client.ExecInspectResult, error)
|
||||
execCreateFunc func(containerID string, options client.ExecCreateOptions) (client.ExecCreateResult, error)
|
||||
createContainerFunc func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform,
|
||||
containerName string) (container.CreateResponse, error)
|
||||
inspectFunc func(string) (container.InspectResponse, error)
|
||||
execInspectFunc func(execID string) (client.ExecInspectResult, error)
|
||||
execCreateFunc func(containerID string, options client.ExecCreateOptions) (client.ExecCreateResult, error)
|
||||
createContainerFunc func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error)
|
||||
containerStartFunc func(containerID string, options client.ContainerStartOptions) error
|
||||
imageCreateFunc func(ctx context.Context, parentReference string, options client.ImageCreateOptions) (client.ImageCreateResult, error)
|
||||
infoFunc func() (system.Info, error)
|
||||
@ -36,10 +30,10 @@ type fakeClient struct {
|
||||
containerStopFunc func(ctx context.Context, containerID string, options client.ContainerStopOptions) error
|
||||
containerKillFunc func(ctx context.Context, containerID, signal string) error
|
||||
containerPruneFunc func(ctx context.Context, options client.ContainerPruneOptions) (client.ContainerPruneResult, error)
|
||||
containerAttachFunc func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error)
|
||||
containerDiffFunc func(ctx context.Context, containerID string) ([]container.FilesystemChange, error)
|
||||
containerAttachFunc func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error)
|
||||
containerDiffFunc func(ctx context.Context, containerID string) (client.ContainerDiffResult, error)
|
||||
containerRenameFunc func(ctx context.Context, oldName, newName string) error
|
||||
containerCommitFunc func(ctx context.Context, container string, options client.ContainerCommitOptions) (container.CommitResponse, error)
|
||||
containerCommitFunc func(ctx context.Context, container string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error)
|
||||
containerPauseFunc func(ctx context.Context, container string) error
|
||||
Version string
|
||||
}
|
||||
@ -76,18 +70,11 @@ func (*fakeClient) ExecStart(context.Context, string, client.ExecStartOptions) (
|
||||
return client.ExecStartResult{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerCreate(
|
||||
_ context.Context,
|
||||
config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
func (f *fakeClient) ContainerCreate(_ context.Context, options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
if f.createContainerFunc != nil {
|
||||
return f.createContainerFunc(config, hostConfig, networkingConfig, platform, containerName)
|
||||
return f.createContainerFunc(options)
|
||||
}
|
||||
return container.CreateResponse{}, nil
|
||||
return client.ContainerCreateResult{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerRemove(ctx context.Context, containerID string, options client.ContainerRemoveOptions) error {
|
||||
@ -192,19 +179,19 @@ func (f *fakeClient) ContainerStop(ctx context.Context, containerID string, opti
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerAttach(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) {
|
||||
func (f *fakeClient) ContainerAttach(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) {
|
||||
if f.containerAttachFunc != nil {
|
||||
return f.containerAttachFunc(ctx, containerID, options)
|
||||
}
|
||||
return client.HijackedResponse{}, nil
|
||||
return client.ContainerAttachResult{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) {
|
||||
func (f *fakeClient) ContainerDiff(ctx context.Context, containerID string, _ client.ContainerDiffOptions) (client.ContainerDiffResult, error) {
|
||||
if f.containerDiffFunc != nil {
|
||||
return f.containerDiffFunc(ctx, containerID)
|
||||
}
|
||||
|
||||
return []container.FilesystemChange{}, nil
|
||||
return client.ContainerDiffResult{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerRename(ctx context.Context, oldName, newName string) error {
|
||||
@ -215,11 +202,11 @@ func (f *fakeClient) ContainerRename(ctx context.Context, oldName, newName strin
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerCommit(ctx context.Context, containerID string, options client.ContainerCommitOptions) (container.CommitResponse, error) {
|
||||
func (f *fakeClient) ContainerCommit(ctx context.Context, containerID string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) {
|
||||
if f.containerCommitFunc != nil {
|
||||
return f.containerCommitFunc(ctx, containerID, options)
|
||||
}
|
||||
return container.CommitResponse{}, nil
|
||||
return client.ContainerCommitResult{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerPause(ctx context.Context, containerID string) error {
|
||||
|
||||
@ -7,7 +7,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/client"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
@ -15,18 +14,14 @@ import (
|
||||
|
||||
func TestRunCommit(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerCommitFunc: func(
|
||||
ctx context.Context,
|
||||
ctr string,
|
||||
options client.ContainerCommitOptions,
|
||||
) (container.CommitResponse, error) {
|
||||
containerCommitFunc: func(ctx context.Context, ctr string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) {
|
||||
assert.Check(t, is.Equal(options.Author, "Author Name <author@name.com>"))
|
||||
assert.Check(t, is.DeepEqual(options.Changes, []string{"EXPOSE 80"}))
|
||||
assert.Check(t, is.Equal(options.Comment, "commit message"))
|
||||
assert.Check(t, is.Equal(options.NoPause, true))
|
||||
assert.Check(t, is.Equal(ctr, "container-id"))
|
||||
|
||||
return container.CommitResponse{ID: "image-id"}, nil
|
||||
return client.ContainerCommitResult{ID: "image-id"}, nil
|
||||
},
|
||||
})
|
||||
|
||||
@ -52,12 +47,8 @@ func TestRunCommitClientError(t *testing.T) {
|
||||
clientError := errors.New("client error")
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerCommitFunc: func(
|
||||
ctx context.Context,
|
||||
ctr string,
|
||||
options client.ContainerCommitOptions,
|
||||
) (container.CommitResponse, error) {
|
||||
return container.CommitResponse{}, clientError
|
||||
containerCommitFunc: func(ctx context.Context, ctr string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) {
|
||||
return client.ContainerCommitResult{}, clientError
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@ -332,7 +332,14 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
|
||||
|
||||
hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = dockerCli.Out().GetTtySize()
|
||||
|
||||
response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, platform, options.name)
|
||||
response, err := dockerCli.Client().ContainerCreate(ctx, client.ContainerCreateOptions{
|
||||
Name: options.name,
|
||||
// Image: config.Image, // TODO(thaJeztah): pass image-ref separate
|
||||
Platform: platform,
|
||||
Config: config,
|
||||
HostConfig: hostConfig,
|
||||
NetworkingConfig: networkingConfig,
|
||||
})
|
||||
if err != nil {
|
||||
// Pull image if it does not exist locally and we have the PullImageMissing option. Default behavior.
|
||||
if errdefs.IsNotFound(err) && namedRef != nil && options.pull == PullImageMissing {
|
||||
@ -346,7 +353,14 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
|
||||
}
|
||||
|
||||
var retryErr error
|
||||
response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, platform, options.name)
|
||||
response, retryErr = dockerCli.Client().ContainerCreate(ctx, client.ContainerCreateOptions{
|
||||
Name: options.name,
|
||||
// Image: config.Image, // TODO(thaJeztah): pass image-ref separate
|
||||
Platform: platform,
|
||||
Config: config,
|
||||
HostConfig: hostConfig,
|
||||
NetworkingConfig: networkingConfig,
|
||||
})
|
||||
if retryErr != nil {
|
||||
return "", retryErr
|
||||
}
|
||||
|
||||
@ -16,10 +16,8 @@ import (
|
||||
"github.com/docker/cli/internal/test/notary"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
"github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/client"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/spf13/pflag"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
@ -117,19 +115,13 @@ func TestCreateContainerImagePullPolicy(t *testing.T) {
|
||||
pullCounter := 0
|
||||
|
||||
apiClient := &fakeClient{
|
||||
createContainerFunc: func(
|
||||
config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
defer func() { tc.ResponseCounter++ }()
|
||||
switch tc.ResponseCounter {
|
||||
case 0:
|
||||
return container.CreateResponse{}, fakeNotFound{}
|
||||
return client.ContainerCreateResult{}, fakeNotFound{}
|
||||
default:
|
||||
return container.CreateResponse{ID: containerID}, nil
|
||||
return client.ContainerCreateResult{ID: containerID}, nil
|
||||
}
|
||||
},
|
||||
imageCreateFunc: func(ctx context.Context, parentReference string, options client.ImageCreateOptions) (client.ImageCreateResult, error) {
|
||||
@ -251,13 +243,8 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Setenv("DOCKER_CONTENT_TRUST", "true")
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{}, errors.New("shouldn't try to pull image")
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
return client.ContainerCreateResult{}, errors.New("shouldn't try to pull image")
|
||||
},
|
||||
})
|
||||
fakeCLI.SetNotaryClient(tc.notaryFunc)
|
||||
@ -296,13 +283,8 @@ func TestNewCreateCommandWithWarnings(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{Warnings: tc.warnings}, nil
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
return client.ContainerCreateResult{Warnings: tc.warnings}, nil
|
||||
},
|
||||
})
|
||||
cmd := newCreateCommand(fakeCLI)
|
||||
@ -335,15 +317,10 @@ func TestCreateContainerWithProxyConfig(t *testing.T) {
|
||||
sort.Strings(expected)
|
||||
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
sort.Strings(config.Env)
|
||||
assert.DeepEqual(t, config.Env, expected)
|
||||
return container.CreateResponse{}, nil
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
sort.Strings(options.Config.Env)
|
||||
assert.DeepEqual(t, options.Config.Env, expected)
|
||||
return client.ContainerCreateResult{}, nil
|
||||
},
|
||||
})
|
||||
fakeCLI.SetConfigFile(&configfile.ConfigFile{
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/moby/moby/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -28,7 +29,7 @@ func newDiffCommand(dockerCLI command.Cli) *cobra.Command {
|
||||
}
|
||||
|
||||
func runDiff(ctx context.Context, dockerCLI command.Cli, containerID string) error {
|
||||
changes, err := dockerCLI.Client().ContainerDiff(ctx, containerID)
|
||||
res, err := dockerCLI.Client().ContainerDiff(ctx, containerID, client.ContainerDiffOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -36,5 +37,5 @@ func runDiff(ctx context.Context, dockerCLI command.Cli, containerID string) err
|
||||
Output: dockerCLI.Out(),
|
||||
Format: newDiffFormat("{{.Type}} {{.Path}}"),
|
||||
}
|
||||
return diffFormatWrite(diffCtx, changes)
|
||||
return diffFormatWrite(diffCtx, res)
|
||||
}
|
||||
|
||||
@ -9,28 +9,28 @@ import (
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/client"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestRunDiff(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerDiffFunc: func(
|
||||
ctx context.Context,
|
||||
containerID string,
|
||||
) ([]container.FilesystemChange, error) {
|
||||
return []container.FilesystemChange{
|
||||
{
|
||||
Kind: container.ChangeModify,
|
||||
Path: "/path/to/file0",
|
||||
},
|
||||
{
|
||||
Kind: container.ChangeAdd,
|
||||
Path: "/path/to/file1",
|
||||
},
|
||||
{
|
||||
Kind: container.ChangeDelete,
|
||||
Path: "/path/to/file2",
|
||||
containerDiffFunc: func(ctx context.Context, containerID string) (client.ContainerDiffResult, error) {
|
||||
return client.ContainerDiffResult{
|
||||
Changes: []container.FilesystemChange{
|
||||
{
|
||||
Kind: container.ChangeModify,
|
||||
Path: "/path/to/file0",
|
||||
},
|
||||
{
|
||||
Kind: container.ChangeAdd,
|
||||
Path: "/path/to/file1",
|
||||
},
|
||||
{
|
||||
Kind: container.ChangeDelete,
|
||||
Path: "/path/to/file2",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
@ -60,11 +60,8 @@ func TestRunDiffClientError(t *testing.T) {
|
||||
clientError := errors.New("client error")
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerDiffFunc: func(
|
||||
ctx context.Context,
|
||||
containerID string,
|
||||
) ([]container.FilesystemChange, error) {
|
||||
return nil, clientError
|
||||
containerDiffFunc: func(ctx context.Context, containerID string) (client.ContainerDiffResult, error) {
|
||||
return client.ContainerDiffResult{}, clientError
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@ -119,7 +119,7 @@ TWO=2
|
||||
},
|
||||
options: func() ExecOptions {
|
||||
o := withDefaultOpts(ExecOptions{})
|
||||
o.EnvFile.Set(tmpFile.Path())
|
||||
_ = o.EnvFile.Set(tmpFile.Path())
|
||||
return o
|
||||
}(),
|
||||
},
|
||||
@ -132,8 +132,8 @@ TWO=2
|
||||
},
|
||||
options: func() ExecOptions {
|
||||
o := withDefaultOpts(ExecOptions{})
|
||||
o.EnvFile.Set(tmpFile.Path())
|
||||
o.Env.Set("ONE=override")
|
||||
_ = o.EnvFile.Set(tmpFile.Path())
|
||||
_ = o.Env.Set("ONE=override")
|
||||
return o
|
||||
}(),
|
||||
},
|
||||
@ -150,7 +150,7 @@ TWO=2
|
||||
|
||||
func TestParseExecNoSuchFile(t *testing.T) {
|
||||
execOpts := withDefaultOpts(ExecOptions{})
|
||||
execOpts.EnvFile.Set("no-such-env-file")
|
||||
assert.Check(t, execOpts.EnvFile.Set("no-such-env-file"))
|
||||
execConfig, err := parseExec(execOpts, &configfile.ConfigFile{})
|
||||
assert.ErrorContains(t, err, "no-such-env-file")
|
||||
assert.Check(t, os.IsNotExist(err))
|
||||
@ -195,7 +195,7 @@ func TestRunExec(t *testing.T) {
|
||||
t.Run(testcase.doc, func(t *testing.T) {
|
||||
fakeCLI := test.NewFakeCli(testcase.client)
|
||||
|
||||
err := RunExec(context.TODO(), fakeCLI, "thecontainer", testcase.options)
|
||||
err := RunExec(context.TODO(), fakeCLI, "the-container", testcase.options)
|
||||
if testcase.expectedError != "" {
|
||||
assert.ErrorContains(t, err, testcase.expectedError)
|
||||
} else if !assert.Check(t, err) {
|
||||
@ -208,7 +208,7 @@ func TestRunExec(t *testing.T) {
|
||||
}
|
||||
|
||||
func execCreateWithID(_ string, _ client.ExecCreateOptions) (client.ExecCreateResult, error) {
|
||||
return client.ExecCreateResult{ExecCreateResponse: container.ExecCreateResponse{ID: "execid"}}, nil
|
||||
return client.ExecCreateResult{ID: "exec-id"}, nil
|
||||
}
|
||||
|
||||
func TestGetExecExitStatus(t *testing.T) {
|
||||
@ -238,9 +238,7 @@ func TestGetExecExitStatus(t *testing.T) {
|
||||
apiClient := &fakeClient{
|
||||
execInspectFunc: func(id string) (client.ExecInspectResult, error) {
|
||||
assert.Check(t, is.Equal(execID, id))
|
||||
return client.ExecInspectResult{
|
||||
ExecInspect: client.ExecInspect{ExitCode: testcase.exitCode},
|
||||
}, testcase.inspectError
|
||||
return client.ExecInspectResult{ExitCode: testcase.exitCode}, testcase.inspectError
|
||||
},
|
||||
}
|
||||
err := getExecExitStatus(context.Background(), apiClient, execID)
|
||||
|
||||
@ -3,6 +3,7 @@ package container
|
||||
import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/client"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -21,9 +22,9 @@ func newDiffFormat(source string) formatter.Format {
|
||||
}
|
||||
|
||||
// diffFormatWrite writes formatted diff using the [formatter.Context].
|
||||
func diffFormatWrite(fmtCtx formatter.Context, changes []container.FilesystemChange) error {
|
||||
func diffFormatWrite(fmtCtx formatter.Context, changes client.ContainerDiffResult) error {
|
||||
return fmtCtx.Write(newDiffContext(), func(format func(subContext formatter.SubContext) error) error {
|
||||
for _, change := range changes {
|
||||
for _, change := range changes.Changes {
|
||||
if err := format(&diffContext{c: change}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/client"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
@ -40,10 +41,12 @@ D: /usr/app/old_app.js
|
||||
},
|
||||
}
|
||||
|
||||
diffs := []container.FilesystemChange{
|
||||
{Kind: container.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: container.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
diffs := client.ContainerDiffResult{
|
||||
Changes: []container.FilesystemChange{
|
||||
{Kind: container.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: container.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
@ -290,7 +290,7 @@ func attachContainer(ctx context.Context, dockerCli command.Cli, containerID str
|
||||
inputStream: in,
|
||||
outputStream: out,
|
||||
errorStream: cerr,
|
||||
resp: resp,
|
||||
resp: resp.HijackedResponse,
|
||||
tty: config.Tty,
|
||||
detachKeys: options.DetachKeys,
|
||||
}
|
||||
@ -301,7 +301,7 @@ func attachContainer(ctx context.Context, dockerCli command.Cli, containerID str
|
||||
return errAttach
|
||||
}()
|
||||
}()
|
||||
return resp.Close, nil
|
||||
return resp.HijackedResponse.Close, nil
|
||||
}
|
||||
|
||||
// withHelp decorates the error with a suggestion to use "--help".
|
||||
|
||||
@ -18,9 +18,7 @@ import (
|
||||
"github.com/moby/moby/api/pkg/streamformatter"
|
||||
"github.com/moby/moby/api/types"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
"github.com/moby/moby/client"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/spf13/pflag"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
@ -56,10 +54,8 @@ func TestRunValidateFlags(t *testing.T) {
|
||||
|
||||
func TestRunLabel(t *testing.T) {
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *ocispec.Platform, _ string) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{
|
||||
ID: "id",
|
||||
}, nil
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
return client.ContainerCreateResult{ID: "id"}, nil
|
||||
},
|
||||
Version: client.MaxAPIVersion,
|
||||
})
|
||||
@ -79,19 +75,19 @@ func TestRunAttach(t *testing.T) {
|
||||
var conn net.Conn
|
||||
attachCh := make(chan struct{})
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *ocispec.Platform, _ string) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{
|
||||
ID: "id",
|
||||
}, nil
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
return client.ContainerCreateResult{ID: "id"}, nil
|
||||
},
|
||||
containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) {
|
||||
containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) {
|
||||
server, clientConn := net.Pipe()
|
||||
conn = server
|
||||
t.Cleanup(func() {
|
||||
_ = server.Close()
|
||||
})
|
||||
attachCh <- struct{}{}
|
||||
return client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), nil
|
||||
return client.ContainerAttachResult{
|
||||
HijackedResponse: client.NewHijackedResponse(clientConn, types.MediaTypeRawStream),
|
||||
}, nil
|
||||
},
|
||||
waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) {
|
||||
responseChan := make(chan container.WaitResponse, 1)
|
||||
@ -150,10 +146,8 @@ func TestRunAttachTermination(t *testing.T) {
|
||||
killCh := make(chan struct{})
|
||||
attachCh := make(chan struct{})
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *ocispec.Platform, _ string) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{
|
||||
ID: "id",
|
||||
}, nil
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
return client.ContainerCreateResult{ID: "id"}, nil
|
||||
},
|
||||
containerKillFunc: func(ctx context.Context, containerID, sig string) error {
|
||||
if sig == "TERM" {
|
||||
@ -161,14 +155,16 @@ func TestRunAttachTermination(t *testing.T) {
|
||||
}
|
||||
return nil
|
||||
},
|
||||
containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) {
|
||||
containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) {
|
||||
server, clientConn := net.Pipe()
|
||||
conn = server
|
||||
t.Cleanup(func() {
|
||||
_ = server.Close()
|
||||
})
|
||||
attachCh <- struct{}{}
|
||||
return client.NewHijackedResponse(clientConn, types.MediaTypeRawStream), nil
|
||||
return client.ContainerAttachResult{
|
||||
HijackedResponse: client.NewHijackedResponse(clientConn, types.MediaTypeRawStream),
|
||||
}, nil
|
||||
},
|
||||
waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) {
|
||||
responseChan := make(chan container.WaitResponse, 1)
|
||||
@ -227,13 +223,11 @@ func TestRunPullTermination(t *testing.T) {
|
||||
|
||||
attachCh := make(chan struct{})
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform, containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{}, errors.New("shouldn't try to create a container")
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
return client.ContainerCreateResult{}, errors.New("shouldn't try to create a container")
|
||||
},
|
||||
containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.HijackedResponse, error) {
|
||||
return client.HijackedResponse{}, errors.New("shouldn't try to attach to a container")
|
||||
containerAttachFunc: func(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error) {
|
||||
return client.ContainerAttachResult{}, errors.New("shouldn't try to attach to a container")
|
||||
},
|
||||
imageCreateFunc: func(ctx context.Context, parentReference string, options client.ImageCreateOptions) (client.ImageCreateResult, error) {
|
||||
server, respReader := net.Pipe()
|
||||
@ -325,13 +319,8 @@ func TestRunCommandWithContentTrustErrors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Setenv("DOCKER_CONTENT_TRUST", "true")
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
platform *ocispec.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{}, errors.New("shouldn't try to pull image")
|
||||
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
|
||||
return client.ContainerCreateResult{}, errors.New("shouldn't try to pull image")
|
||||
},
|
||||
})
|
||||
fakeCLI.SetNotaryClient(tc.notaryFunc)
|
||||
|
||||
@ -116,7 +116,7 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er
|
||||
if errAttach != nil {
|
||||
return errAttach
|
||||
}
|
||||
defer resp.Close()
|
||||
defer resp.HijackedResponse.Close()
|
||||
|
||||
cErr := make(chan error, 1)
|
||||
|
||||
@ -127,7 +127,7 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er
|
||||
inputStream: in,
|
||||
outputStream: dockerCli.Out(),
|
||||
errorStream: dockerCli.Err(),
|
||||
resp: resp,
|
||||
resp: resp.HijackedResponse,
|
||||
tty: c.Config.Tty,
|
||||
detachKeys: options.DetachKeys,
|
||||
}
|
||||
@ -166,7 +166,8 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er
|
||||
}
|
||||
}
|
||||
if attachErr := <-cErr; attachErr != nil {
|
||||
if _, ok := attachErr.(term.EscapeError); ok {
|
||||
var escapeError term.EscapeError
|
||||
if errors.As(attachErr, &escapeError) {
|
||||
// The user entered the detach escape sequence.
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -40,10 +40,10 @@ func NewVolumeFormat(source string, quiet bool) Format {
|
||||
}
|
||||
|
||||
// VolumeWrite writes formatted volumes using the Context
|
||||
func VolumeWrite(ctx Context, volumes []*volume.Volume) error {
|
||||
func VolumeWrite(ctx Context, volumes []volume.Volume) error {
|
||||
render := func(format func(subContext SubContext) error) error {
|
||||
for _, vol := range volumes {
|
||||
if err := format(&volumeContext{v: *vol}); err != nil {
|
||||
if err := format(&volumeContext{v: vol}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ foobar_bar
|
||||
},
|
||||
}
|
||||
|
||||
volumes := []*volume.Volume{
|
||||
volumes := []volume.Volume{
|
||||
{Name: "foobar_baz", Driver: "foo"},
|
||||
{Name: "foobar_bar", Driver: "bar"},
|
||||
}
|
||||
@ -144,7 +144,7 @@ foobar_bar
|
||||
}
|
||||
|
||||
func TestVolumeContextWriteJSON(t *testing.T) {
|
||||
volumes := []*volume.Volume{
|
||||
volumes := []volume.Volume{
|
||||
{Driver: "foo", Name: "foobar_baz"},
|
||||
{Driver: "bar", Name: "foobar_bar"},
|
||||
}
|
||||
@ -167,7 +167,7 @@ func TestVolumeContextWriteJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVolumeContextWriteJSONField(t *testing.T) {
|
||||
volumes := []*volume.Volume{
|
||||
volumes := []volume.Volume{
|
||||
{Driver: "foo", Name: "foobar_baz"},
|
||||
{Driver: "bar", Name: "foobar_bar"},
|
||||
}
|
||||
|
||||
@ -50,7 +50,6 @@ func TestNewImportCommandInvalidFile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewImportCommandSuccess(t *testing.T) {
|
||||
t.Skip("FIXME(thaJeztah): how to mock this?")
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
|
||||
@ -97,7 +97,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
|
||||
// Body: io.NopCloser(strings.NewReader(`{"ID": "1"}`)),
|
||||
// JSON: true,
|
||||
// }, nil
|
||||
return client.ImageLoadResult{}, nil
|
||||
return client.ImageLoadResult{JSON: true}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -86,7 +86,7 @@ func runRemove(ctx context.Context, dockerCLI command.Cli, opts removeOptions, i
|
||||
}
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
for _, del := range res.Deleted {
|
||||
for _, del := range res.Items {
|
||||
if del.Deleted != "" {
|
||||
_, _ = fmt.Fprintln(dockerCLI.Out(), "Deleted:", del.Deleted)
|
||||
} else {
|
||||
|
||||
@ -88,7 +88,7 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
|
||||
imageRemoveFunc: func(img string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error) {
|
||||
assert.Check(t, is.Equal("image1", img))
|
||||
return client.ImageRemoveResult{
|
||||
Deleted: []image.DeleteResponse{{Deleted: img}},
|
||||
Items: []image.DeleteResponse{{Deleted: img}},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
@ -109,7 +109,7 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
|
||||
imageRemoveFunc: func(img string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error) {
|
||||
assert.Check(t, is.Equal("image1", img))
|
||||
return client.ImageRemoveResult{
|
||||
Deleted: []image.DeleteResponse{{Untagged: img}},
|
||||
Items: []image.DeleteResponse{{Untagged: img}},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
@ -119,11 +119,11 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
|
||||
imageRemoveFunc: func(img string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error) {
|
||||
if img == "image1" {
|
||||
return client.ImageRemoveResult{
|
||||
Deleted: []image.DeleteResponse{{Untagged: img}},
|
||||
Items: []image.DeleteResponse{{Untagged: img}},
|
||||
}, nil
|
||||
}
|
||||
return client.ImageRemoveResult{
|
||||
Deleted: []image.DeleteResponse{{Deleted: img}},
|
||||
Items: []image.DeleteResponse{{Deleted: img}},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
|
||||
@ -59,8 +59,8 @@ func TestNodeDemoteNoChange(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if options.Node.Role != swarm.NodeRoleWorker {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Node.Role))
|
||||
if options.Spec.Role != swarm.NodeRoleWorker {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Spec.Role))
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
@ -78,8 +78,8 @@ func TestNodeDemoteMultipleNode(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if options.Node.Role != swarm.NodeRoleWorker {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Node.Role))
|
||||
if options.Spec.Role != swarm.NodeRoleWorker {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role worker, got " + string(options.Spec.Role))
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
|
||||
@ -59,8 +59,8 @@ func TestNodePromoteNoChange(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if options.Node.Role != swarm.NodeRoleManager {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Node.Role))
|
||||
if options.Spec.Role != swarm.NodeRoleManager {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Spec.Role))
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
@ -78,8 +78,8 @@ func TestNodePromoteMultipleNode(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if options.Node.Role != swarm.NodeRoleManager {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Node.Role))
|
||||
if options.Spec.Role != swarm.NodeRoleManager {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role manager, got" + string(options.Spec.Role))
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
|
||||
@ -66,7 +66,7 @@ func updateNodes(ctx context.Context, apiClient client.NodeAPIClient, nodes []st
|
||||
}
|
||||
_, err = apiClient.NodeUpdate(ctx, res.Node.ID, client.NodeUpdateOptions{
|
||||
Version: res.Node.Version,
|
||||
Node: res.Node.Spec,
|
||||
Spec: res.Node.Spec,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@ -91,8 +91,8 @@ func TestNodeUpdate(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if options.Node.Role != swarm.NodeRoleManager {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role manager, got " + string(options.Node.Role))
|
||||
if options.Spec.Role != swarm.NodeRoleManager {
|
||||
return client.NodeUpdateResult{}, errors.New("expected role manager, got " + string(options.Spec.Role))
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
@ -108,8 +108,8 @@ func TestNodeUpdate(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if options.Node.Availability != swarm.NodeAvailabilityDrain {
|
||||
return client.NodeUpdateResult{}, errors.New("expected drain availability, got " + string(options.Node.Availability))
|
||||
if options.Spec.Availability != swarm.NodeAvailabilityDrain {
|
||||
return client.NodeUpdateResult{}, errors.New("expected drain availability, got " + string(options.Spec.Availability))
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
@ -125,8 +125,8 @@ func TestNodeUpdate(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if _, present := options.Node.Annotations.Labels["lbl"]; !present {
|
||||
return client.NodeUpdateResult{}, fmt.Errorf("expected 'lbl' label, got %v", options.Node.Annotations.Labels)
|
||||
if _, present := options.Spec.Annotations.Labels["lbl"]; !present {
|
||||
return client.NodeUpdateResult{}, fmt.Errorf("expected 'lbl' label, got %v", options.Spec.Annotations.Labels)
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
@ -142,8 +142,8 @@ func TestNodeUpdate(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if value, present := options.Node.Annotations.Labels["key"]; !present || value != "value" {
|
||||
return client.NodeUpdateResult{}, fmt.Errorf("expected 'key' label to be 'value', got %v", options.Node.Annotations.Labels)
|
||||
if value, present := options.Spec.Annotations.Labels["key"]; !present || value != "value" {
|
||||
return client.NodeUpdateResult{}, fmt.Errorf("expected 'key' label to be 'value', got %v", options.Spec.Annotations.Labels)
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
@ -161,8 +161,8 @@ func TestNodeUpdate(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, options client.NodeUpdateOptions) (client.NodeUpdateResult, error) {
|
||||
if len(options.Node.Annotations.Labels) > 0 {
|
||||
return client.NodeUpdateResult{}, fmt.Errorf("expected no labels, got %v", options.Node.Annotations.Labels)
|
||||
if len(options.Spec.Annotations.Labels) > 0 {
|
||||
return client.NodeUpdateResult{}, fmt.Errorf("expected no labels, got %v", options.Spec.Annotations.Labels)
|
||||
}
|
||||
return client.NodeUpdateResult{}, nil
|
||||
},
|
||||
|
||||
@ -3,6 +3,7 @@ package plugin
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/client"
|
||||
@ -78,5 +79,5 @@ func (c *fakeClient) PluginUpgrade(_ context.Context, name string, options clien
|
||||
return c.pluginUpgradeFunc(name, options)
|
||||
}
|
||||
// FIXME(thaJeztah): how to mock this?
|
||||
return nil, nil
|
||||
return io.NopCloser(strings.NewReader("")), nil
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import (
|
||||
type fakeClient struct {
|
||||
client.Client
|
||||
serviceInspectFunc func(ctx context.Context, serviceID string, options client.ServiceInspectOptions) (client.ServiceInspectResult, error)
|
||||
serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
serviceUpdateFunc func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
serviceListFunc func(context.Context, client.ServiceListOptions) (client.ServiceListResult, error)
|
||||
taskListFunc func(context.Context, client.TaskListOptions) (client.TaskListResult, error)
|
||||
infoFunc func(ctx context.Context) (system.Info, error)
|
||||
@ -52,9 +52,9 @@ func (f *fakeClient) ServiceList(ctx context.Context, options client.ServiceList
|
||||
return client.ServiceListResult{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
if f.serviceUpdateFunc != nil {
|
||||
return f.serviceUpdateFunc(ctx, serviceID, version, service, options)
|
||||
return f.serviceUpdateFunc(ctx, serviceID, options)
|
||||
}
|
||||
|
||||
return client.ServiceUpdateResult{}, nil
|
||||
|
||||
@ -95,7 +95,6 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
|
||||
|
||||
func runCreate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opts *serviceOptions) error {
|
||||
apiClient := dockerCLI.Client()
|
||||
createOpts := client.ServiceCreateOptions{}
|
||||
|
||||
service, err := opts.ToService(ctx, apiClient, flags)
|
||||
if err != nil {
|
||||
@ -121,19 +120,22 @@ func runCreate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet,
|
||||
}
|
||||
|
||||
// only send auth if flag was set
|
||||
var encodedAuth string
|
||||
if opts.registryAuth {
|
||||
// Retrieve encoded auth token from the image reference
|
||||
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), opts.image)
|
||||
var err error
|
||||
encodedAuth, err = command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), opts.image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
createOpts.EncodedRegistryAuth = encodedAuth
|
||||
}
|
||||
|
||||
// query registry if flag disabling it was not set
|
||||
createOpts.QueryRegistry = !opts.noResolveImage
|
||||
response, err := apiClient.ServiceCreate(ctx, client.ServiceCreateOptions{
|
||||
Spec: service,
|
||||
|
||||
response, err := apiClient.ServiceCreate(ctx, service, createOpts)
|
||||
EncodedRegistryAuth: encodedAuth,
|
||||
QueryRegistry: !opts.noResolveImage, // query registry if flag disabling it was not set.
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -40,7 +40,9 @@ func runRollback(ctx context.Context, dockerCLI command.Cli, options *serviceOpt
|
||||
return err
|
||||
}
|
||||
|
||||
response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, res.Service.Version, res.Service.Spec, client.ServiceUpdateOptions{
|
||||
response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, client.ServiceUpdateOptions{
|
||||
Version: res.Service.Version,
|
||||
Spec: res.Service.Spec,
|
||||
Rollback: "previous", // TODO(thaJeztah): this should have a const defined
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@ -8,7 +8,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
"github.com/moby/moby/client"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
@ -18,7 +17,7 @@ func TestRollback(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
serviceUpdateFunc func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
expectedDockerCliErr string
|
||||
}{
|
||||
{
|
||||
@ -28,7 +27,7 @@ func TestRollback(t *testing.T) {
|
||||
{
|
||||
name: "rollback-service-with-warnings",
|
||||
args: []string{"service-id"},
|
||||
serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
serviceUpdateFunc: func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
return client.ServiceUpdateResult{
|
||||
Warnings: []string{
|
||||
"- warning 1",
|
||||
@ -59,7 +58,7 @@ func TestRollbackWithErrors(t *testing.T) {
|
||||
name string
|
||||
args []string
|
||||
serviceInspectFunc func(ctx context.Context, serviceID string, options client.ServiceInspectOptions) (client.ServiceInspectResult, error)
|
||||
serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, opts client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
serviceUpdateFunc func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -82,7 +81,7 @@ func TestRollbackWithErrors(t *testing.T) {
|
||||
{
|
||||
name: "service-update-failed",
|
||||
args: []string{"service-id"},
|
||||
serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
serviceUpdateFunc: func(ctx context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
return client.ServiceUpdateResult{}, fmt.Errorf("no such services: %s", serviceID)
|
||||
},
|
||||
expectedError: "no such services: service-id",
|
||||
|
||||
@ -108,7 +108,10 @@ func runServiceScale(ctx context.Context, apiClient client.ServiceAPIClient, ser
|
||||
return nil, errors.New("scale can only be used with replicated or replicated-job mode")
|
||||
}
|
||||
|
||||
response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, res.Service.Version, res.Service.Spec, client.ServiceUpdateOptions{})
|
||||
response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, client.ServiceUpdateOptions{
|
||||
Version: res.Service.Version,
|
||||
Spec: res.Service.Spec,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -46,14 +46,14 @@ func newUpdateCommand(dockerCLI command.Cli) *cobra.Command {
|
||||
flags.String("image", "", "Service image tag")
|
||||
flags.Var(&ShlexOpt{}, "args", "Service command args")
|
||||
flags.Bool(flagRollback, false, "Rollback to previous specification")
|
||||
flags.SetAnnotation(flagRollback, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagRollback, "version", []string{"1.25"})
|
||||
flags.Bool("force", false, "Force update even if no changes require it")
|
||||
flags.SetAnnotation("force", "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation("force", "version", []string{"1.25"})
|
||||
addServiceFlags(flags, options, nil)
|
||||
|
||||
flags.Var(newListOptsVar(), flagEnvRemove, "Remove an environment variable")
|
||||
flags.Var(newListOptsVar(), flagGroupRemove, "Remove a previously added supplementary user group from the container")
|
||||
flags.SetAnnotation(flagGroupRemove, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagGroupRemove, "version", []string{"1.25"})
|
||||
flags.Var(newListOptsVar(), flagLabelRemove, "Remove a label by its key")
|
||||
flags.Var(newListOptsVar(), flagContainerLabelRemove, "Remove a container label by its key")
|
||||
flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path")
|
||||
@ -61,65 +61,65 @@ func newUpdateCommand(dockerCLI command.Cli) *cobra.Command {
|
||||
flags.Var(&swarmopts.PortOpt{}, flagPublishRemove, "Remove a published port by its target port")
|
||||
flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint")
|
||||
flags.Var(newListOptsVar(), flagDNSRemove, "Remove a custom DNS server")
|
||||
flags.SetAnnotation(flagDNSRemove, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagDNSRemove, "version", []string{"1.25"})
|
||||
flags.Var(newListOptsVar(), flagDNSOptionRemove, "Remove a DNS option")
|
||||
flags.SetAnnotation(flagDNSOptionRemove, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagDNSOptionRemove, "version", []string{"1.25"})
|
||||
flags.Var(newListOptsVar(), flagDNSSearchRemove, "Remove a DNS search domain")
|
||||
flags.SetAnnotation(flagDNSSearchRemove, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagDNSSearchRemove, "version", []string{"1.25"})
|
||||
flags.Var(newListOptsVar(), flagHostRemove, `Remove a custom host-to-IP mapping ("host:ip")`)
|
||||
flags.SetAnnotation(flagHostRemove, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagHostRemove, "version", []string{"1.25"})
|
||||
flags.Var(&options.labels, flagLabelAdd, "Add or update a service label")
|
||||
flags.Var(&options.containerLabels, flagContainerLabelAdd, "Add or update a container label")
|
||||
flags.Var(&options.env, flagEnvAdd, "Add or update an environment variable")
|
||||
flags.Var(newListOptsVar(), flagSecretRemove, "Remove a secret")
|
||||
flags.SetAnnotation(flagSecretRemove, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagSecretRemove, "version", []string{"1.25"})
|
||||
flags.Var(&options.secrets, flagSecretAdd, "Add or update a secret on a service")
|
||||
flags.SetAnnotation(flagSecretAdd, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagSecretAdd, "version", []string{"1.25"})
|
||||
|
||||
flags.Var(newListOptsVar(), flagConfigRemove, "Remove a configuration file")
|
||||
flags.SetAnnotation(flagConfigRemove, "version", []string{"1.30"})
|
||||
_ = flags.SetAnnotation(flagConfigRemove, "version", []string{"1.30"})
|
||||
flags.Var(&options.configs, flagConfigAdd, "Add or update a config file on a service")
|
||||
flags.SetAnnotation(flagConfigAdd, "version", []string{"1.30"})
|
||||
_ = flags.SetAnnotation(flagConfigAdd, "version", []string{"1.30"})
|
||||
|
||||
flags.Var(&options.mounts, flagMountAdd, "Add or update a mount on a service")
|
||||
flags.Var(&options.constraints, flagConstraintAdd, "Add or update a placement constraint")
|
||||
flags.Var(&options.placementPrefs, flagPlacementPrefAdd, "Add a placement preference")
|
||||
flags.SetAnnotation(flagPlacementPrefAdd, "version", []string{"1.28"})
|
||||
_ = flags.SetAnnotation(flagPlacementPrefAdd, "version", []string{"1.28"})
|
||||
flags.Var(&placementPrefOpts{}, flagPlacementPrefRemove, "Remove a placement preference")
|
||||
flags.SetAnnotation(flagPlacementPrefRemove, "version", []string{"1.28"})
|
||||
_ = flags.SetAnnotation(flagPlacementPrefRemove, "version", []string{"1.28"})
|
||||
flags.Var(&options.networks, flagNetworkAdd, "Add a network")
|
||||
flags.SetAnnotation(flagNetworkAdd, "version", []string{"1.29"})
|
||||
_ = flags.SetAnnotation(flagNetworkAdd, "version", []string{"1.29"})
|
||||
flags.Var(newListOptsVar(), flagNetworkRemove, "Remove a network")
|
||||
flags.SetAnnotation(flagNetworkRemove, "version", []string{"1.29"})
|
||||
_ = flags.SetAnnotation(flagNetworkRemove, "version", []string{"1.29"})
|
||||
flags.Var(&options.endpoint.publishPorts, flagPublishAdd, "Add or update a published port")
|
||||
flags.Var(&options.groups, flagGroupAdd, "Add an additional supplementary user group to the container")
|
||||
flags.SetAnnotation(flagGroupAdd, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagGroupAdd, "version", []string{"1.25"})
|
||||
flags.Var(&options.dns, flagDNSAdd, "Add or update a custom DNS server")
|
||||
flags.SetAnnotation(flagDNSAdd, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagDNSAdd, "version", []string{"1.25"})
|
||||
flags.Var(&options.dnsOption, flagDNSOptionAdd, "Add or update a DNS option")
|
||||
flags.SetAnnotation(flagDNSOptionAdd, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagDNSOptionAdd, "version", []string{"1.25"})
|
||||
flags.Var(&options.dnsSearch, flagDNSSearchAdd, "Add or update a custom DNS search domain")
|
||||
flags.SetAnnotation(flagDNSSearchAdd, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagDNSSearchAdd, "version", []string{"1.25"})
|
||||
flags.Var(&options.hosts, flagHostAdd, `Add a custom host-to-IP mapping ("host:ip")`)
|
||||
flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"})
|
||||
_ = flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"})
|
||||
flags.BoolVar(&options.init, flagInit, false, "Use an init inside each service container to forward signals and reap processes")
|
||||
flags.SetAnnotation(flagInit, "version", []string{"1.37"})
|
||||
_ = flags.SetAnnotation(flagInit, "version", []string{"1.37"})
|
||||
flags.Var(&options.sysctls, flagSysCtlAdd, "Add or update a Sysctl option")
|
||||
flags.SetAnnotation(flagSysCtlAdd, "version", []string{"1.40"})
|
||||
_ = flags.SetAnnotation(flagSysCtlAdd, "version", []string{"1.40"})
|
||||
flags.Var(newListOptsVar(), flagSysCtlRemove, "Remove a Sysctl option")
|
||||
flags.SetAnnotation(flagSysCtlRemove, "version", []string{"1.40"})
|
||||
_ = flags.SetAnnotation(flagSysCtlRemove, "version", []string{"1.40"})
|
||||
flags.Var(&options.ulimits, flagUlimitAdd, "Add or update a ulimit option")
|
||||
flags.SetAnnotation(flagUlimitAdd, "version", []string{"1.41"})
|
||||
_ = flags.SetAnnotation(flagUlimitAdd, "version", []string{"1.41"})
|
||||
flags.Var(newListOptsVar(), flagUlimitRemove, "Remove a ulimit option")
|
||||
flags.SetAnnotation(flagUlimitRemove, "version", []string{"1.41"})
|
||||
_ = flags.SetAnnotation(flagUlimitRemove, "version", []string{"1.41"})
|
||||
flags.Int64Var(&options.oomScoreAdj, flagOomScoreAdj, 0, "Tune host's OOM preferences (-1000 to 1000) ")
|
||||
flags.SetAnnotation(flagOomScoreAdj, "version", []string{"1.46"})
|
||||
_ = flags.SetAnnotation(flagOomScoreAdj, "version", []string{"1.46"})
|
||||
|
||||
// Add needs parsing, Remove only needs the key
|
||||
flags.Var(newListOptsVar(), flagGenericResourcesRemove, "Remove a Generic resource")
|
||||
flags.SetAnnotation(flagGenericResourcesRemove, "version", []string{"1.32"})
|
||||
_ = flags.SetAnnotation(flagGenericResourcesRemove, "version", []string{"1.32"})
|
||||
flags.Var(newListOptsVarWithValidator(ValidateSingleGenericResource), flagGenericResourcesAdd, "Add a Generic resource")
|
||||
flags.SetAnnotation(flagGenericResourcesAdd, "version", []string{"1.32"})
|
||||
_ = flags.SetAnnotation(flagGenericResourcesAdd, "version", []string{"1.32"})
|
||||
|
||||
// TODO(thaJeztah): add completion for capabilities, stop-signal (currently non-exported in container package)
|
||||
// _ = cmd.RegisterFlagCompletionFunc(flagCapAdd, completeLinuxCapabilityNames)
|
||||
@ -164,7 +164,6 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet,
|
||||
return err
|
||||
}
|
||||
|
||||
spec := &res.Service.Spec
|
||||
if rollback {
|
||||
// Rollback can't be combined with other flags.
|
||||
otherFlagsPassed := false
|
||||
@ -182,10 +181,12 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet,
|
||||
}
|
||||
|
||||
updateOpts := client.ServiceUpdateOptions{}
|
||||
rollbackAction := "none"
|
||||
if rollback {
|
||||
updateOpts.Rollback = "previous"
|
||||
rollbackAction = "previous"
|
||||
}
|
||||
|
||||
spec := &res.Service.Spec
|
||||
err = updateService(ctx, apiClient, flags, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -202,14 +203,12 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spec.TaskTemplate.ContainerSpec.Secrets = updatedSecrets
|
||||
|
||||
updatedConfigs, err := getUpdatedConfigs(ctx, apiClient, flags, spec.TaskTemplate.ContainerSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spec.TaskTemplate.ContainerSpec.Configs = updatedConfigs
|
||||
|
||||
// set the credential spec value after get the updated configs, because we
|
||||
@ -218,24 +217,31 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet,
|
||||
updateCredSpecConfig(flags, spec.TaskTemplate.ContainerSpec)
|
||||
|
||||
// only send auth if flag was set
|
||||
sendAuth, err := flags.GetBool(flagRegistryAuth)
|
||||
if err != nil {
|
||||
var encodedAuth string
|
||||
var registryAuthFrom string
|
||||
if ok, err := flags.GetBool(flagRegistryAuth); err != nil {
|
||||
return err
|
||||
}
|
||||
if sendAuth {
|
||||
} else if ok {
|
||||
// Retrieve encoded auth token from the image reference
|
||||
// This would be the old image if it didn't change in this update
|
||||
image := spec.TaskTemplate.ContainerSpec.Image
|
||||
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), image)
|
||||
var err error
|
||||
encodedAuth, err = command.RetrieveAuthTokenFromImage(dockerCLI.ConfigFile(), spec.TaskTemplate.ContainerSpec.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateOpts.EncodedRegistryAuth = encodedAuth
|
||||
} else {
|
||||
updateOpts.RegistryAuthFrom = swarm.RegistryAuthFromSpec
|
||||
registryAuthFrom = swarm.RegistryAuthFromSpec
|
||||
}
|
||||
|
||||
response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, res.Service.Version, *spec, updateOpts)
|
||||
response, err := apiClient.ServiceUpdate(ctx, res.Service.ID, client.ServiceUpdateOptions{
|
||||
Version: res.Service.Version,
|
||||
Spec: *spec,
|
||||
|
||||
EncodedRegistryAuth: encodedAuth,
|
||||
RegistryAuthFrom: registryAuthFrom,
|
||||
Rollback: rollbackAction,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ type fakeClient struct {
|
||||
nodeListFunc func(options client.NodeListOptions) (client.NodeListResult, error)
|
||||
taskListFunc func(options client.TaskListOptions) (client.TaskListResult, error)
|
||||
nodeInspectFunc func(ref string) (client.NodeInspectResult, error)
|
||||
serviceUpdateFunc func(serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
serviceUpdateFunc func(serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error)
|
||||
serviceRemoveFunc func(serviceID string) (client.ServiceRemoveResult, error)
|
||||
networkRemoveFunc func(networkID string) error
|
||||
secretRemoveFunc func(secretID string) (client.SecretRemoveResult, error)
|
||||
@ -130,9 +130,9 @@ func (cli *fakeClient) NodeInspect(_ context.Context, ref string, _ client.NodeI
|
||||
return client.NodeInspectResult{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceUpdate(_ context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
func (cli *fakeClient) ServiceUpdate(_ context.Context, serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
if cli.serviceUpdateFunc != nil {
|
||||
return cli.serviceUpdateFunc(serviceID, version, service, options)
|
||||
return cli.serviceUpdateFunc(serviceID, options)
|
||||
}
|
||||
|
||||
return client.ServiceUpdateResult{}, nil
|
||||
|
||||
@ -233,7 +233,10 @@ func deployServices(ctx context.Context, dockerCLI command.Cli, services map[str
|
||||
if svc, exists := existingServiceMap[name]; exists {
|
||||
_, _ = fmt.Fprintf(out, "Updating service %s (id: %s)\n", name, svc.ID)
|
||||
|
||||
updateOpts := client.ServiceUpdateOptions{EncodedRegistryAuth: encodedAuth}
|
||||
updateOpts := client.ServiceUpdateOptions{
|
||||
Version: svc.Version,
|
||||
EncodedRegistryAuth: encodedAuth,
|
||||
}
|
||||
|
||||
switch resolveImage {
|
||||
case resolveImageAlways:
|
||||
@ -265,7 +268,8 @@ func deployServices(ctx context.Context, dockerCLI command.Cli, services map[str
|
||||
// TODO move this to API client?
|
||||
serviceSpec.TaskTemplate.ForceUpdate = svc.Spec.TaskTemplate.ForceUpdate
|
||||
|
||||
response, err := apiClient.ServiceUpdate(ctx, svc.ID, svc.Version, serviceSpec, updateOpts)
|
||||
updateOpts.Spec = serviceSpec
|
||||
response, err := apiClient.ServiceUpdate(ctx, svc.ID, updateOpts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update service %s: %w", name, err)
|
||||
}
|
||||
@ -281,7 +285,8 @@ func deployServices(ctx context.Context, dockerCLI command.Cli, services map[str
|
||||
// query registry if flag disabling it was not set
|
||||
queryRegistry := resolveImage == resolveImageAlways || resolveImage == resolveImageChanged
|
||||
|
||||
response, err := apiClient.ServiceCreate(ctx, serviceSpec, client.ServiceCreateOptions{
|
||||
response, err := apiClient.ServiceCreate(ctx, client.ServiceCreateOptions{
|
||||
Spec: serviceSpec,
|
||||
EncodedRegistryAuth: encodedAuth,
|
||||
QueryRegistry: queryRegistry,
|
||||
})
|
||||
|
||||
@ -42,10 +42,7 @@ func TestPruneServices(t *testing.T) {
|
||||
func TestServiceUpdateResolveImageChanged(t *testing.T) {
|
||||
namespace := convert.NewNamespace("mystack")
|
||||
|
||||
var (
|
||||
receivedOptions client.ServiceUpdateOptions
|
||||
receivedService swarm.ServiceSpec
|
||||
)
|
||||
var receivedOptions client.ServiceUpdateOptions
|
||||
|
||||
fakeCli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options client.ServiceListOptions) (client.ServiceListResult, error) {
|
||||
@ -68,9 +65,8 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) {
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
serviceUpdateFunc: func(serviceID string, version swarm.Version, service swarm.ServiceSpec, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
serviceUpdateFunc: func(serviceID string, options client.ServiceUpdateOptions) (client.ServiceUpdateResult, error) {
|
||||
receivedOptions = options
|
||||
receivedService = service
|
||||
return client.ServiceUpdateResult{}, nil
|
||||
},
|
||||
})
|
||||
@ -113,10 +109,9 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) {
|
||||
_, err := deployServices(ctx, fakeCli, spec, namespace, false, resolveImageChanged)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(receivedOptions.QueryRegistry, tc.expectedQueryRegistry))
|
||||
assert.Check(t, is.Equal(receivedService.TaskTemplate.ContainerSpec.Image, tc.expectedImage))
|
||||
assert.Check(t, is.Equal(receivedService.TaskTemplate.ForceUpdate, tc.expectedForceUpdate))
|
||||
assert.Check(t, is.Equal(receivedOptions.Spec.TaskTemplate.ContainerSpec.Image, tc.expectedImage))
|
||||
assert.Check(t, is.Equal(receivedOptions.Spec.TaskTemplate.ForceUpdate, tc.expectedForceUpdate))
|
||||
|
||||
receivedService = swarm.ServiceSpec{}
|
||||
receivedOptions = client.ServiceUpdateOptions{}
|
||||
})
|
||||
}
|
||||
|
||||
@ -84,8 +84,9 @@ func runCA(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opt
|
||||
}
|
||||
|
||||
updateSwarmSpec(&res.Swarm.Spec, flags, opts)
|
||||
if _, err := apiClient.SwarmUpdate(ctx, res.Swarm.Version, client.SwarmUpdateOptions{
|
||||
Swarm: res.Swarm.Spec,
|
||||
if _, err := apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{
|
||||
Version: res.Swarm.Version,
|
||||
Spec: res.Swarm.Spec,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ type swarmUpdateRecorder struct {
|
||||
}
|
||||
|
||||
func (s *swarmUpdateRecorder) swarmUpdate(opts client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) {
|
||||
s.spec = opts.Swarm
|
||||
s.spec = opts.Spec
|
||||
return client.SwarmUpdateResult{}, nil
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@ package swarm
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
"github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/client"
|
||||
)
|
||||
@ -70,7 +69,7 @@ func (cli *fakeClient) SwarmLeave(context.Context, client.SwarmLeaveOptions) (cl
|
||||
return client.SwarmLeaveResult{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmUpdate(_ context.Context, _ swarm.Version, options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) {
|
||||
func (cli *fakeClient) SwarmUpdate(_ context.Context, options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) {
|
||||
if cli.swarmUpdateFunc != nil {
|
||||
return cli.swarmUpdateFunc(options)
|
||||
}
|
||||
|
||||
@ -58,8 +58,9 @@ func runJoinToken(ctx context.Context, dockerCLI command.Cli, opts joinTokenOpti
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = apiClient.SwarmUpdate(ctx, res.Swarm.Version, client.SwarmUpdateOptions{
|
||||
Swarm: res.Swarm.Spec,
|
||||
_, err = apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{
|
||||
Version: res.Swarm.Version,
|
||||
Spec: res.Swarm.Spec,
|
||||
RotateWorkerToken: worker,
|
||||
RotateManagerToken: manager,
|
||||
})
|
||||
|
||||
@ -55,8 +55,10 @@ func runUnlockKey(ctx context.Context, dockerCLI command.Cli, opts unlockKeyOpti
|
||||
return errors.New("cannot rotate because autolock is not turned on")
|
||||
}
|
||||
|
||||
_, err = apiClient.SwarmUpdate(ctx, res.Swarm.Version, client.SwarmUpdateOptions{
|
||||
Swarm: res.Swarm.Spec,
|
||||
_, err = apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{
|
||||
Version: res.Swarm.Version,
|
||||
Spec: res.Swarm.Spec,
|
||||
|
||||
RotateManagerUnlockKey: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@ -54,8 +54,9 @@ func runUpdate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet,
|
||||
|
||||
curAutoLock := sw.Swarm.Spec.EncryptionConfig.AutoLockManagers
|
||||
|
||||
_, err = apiClient.SwarmUpdate(ctx, sw.Swarm.Version, client.SwarmUpdateOptions{
|
||||
Swarm: sw.Swarm.Spec,
|
||||
_, err = apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{
|
||||
Version: sw.Swarm.Version,
|
||||
Spec: sw.Swarm.Spec,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@ -120,33 +120,33 @@ func TestSwarmUpdate(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
swarmUpdateFunc: func(options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) {
|
||||
if *options.Swarm.Orchestration.TaskHistoryRetentionLimit != 10 {
|
||||
if *options.Spec.Orchestration.TaskHistoryRetentionLimit != 10 {
|
||||
return client.SwarmUpdateResult{}, errors.New("historyLimit not correctly set")
|
||||
}
|
||||
heartbeatDuration, err := time.ParseDuration("10s")
|
||||
if err != nil {
|
||||
return client.SwarmUpdateResult{}, err
|
||||
}
|
||||
if options.Swarm.Dispatcher.HeartbeatPeriod != heartbeatDuration {
|
||||
if options.Spec.Dispatcher.HeartbeatPeriod != heartbeatDuration {
|
||||
return client.SwarmUpdateResult{}, errors.New("heartbeatPeriodLimit not correctly set")
|
||||
}
|
||||
certExpiryDuration, err := time.ParseDuration("20s")
|
||||
if err != nil {
|
||||
return client.SwarmUpdateResult{}, err
|
||||
}
|
||||
if options.Swarm.CAConfig.NodeCertExpiry != certExpiryDuration {
|
||||
if options.Spec.CAConfig.NodeCertExpiry != certExpiryDuration {
|
||||
return client.SwarmUpdateResult{}, errors.New("certExpiry not correctly set")
|
||||
}
|
||||
if len(options.Swarm.CAConfig.ExternalCAs) != 1 || options.Swarm.CAConfig.ExternalCAs[0].CACert != "trust-root" {
|
||||
if len(options.Spec.CAConfig.ExternalCAs) != 1 || options.Spec.CAConfig.ExternalCAs[0].CACert != "trust-root" {
|
||||
return client.SwarmUpdateResult{}, errors.New("externalCA not correctly set")
|
||||
}
|
||||
if *options.Swarm.Raft.KeepOldSnapshots != 10 {
|
||||
if *options.Spec.Raft.KeepOldSnapshots != 10 {
|
||||
return client.SwarmUpdateResult{}, errors.New("keepOldSnapshots not correctly set")
|
||||
}
|
||||
if options.Swarm.Raft.SnapshotInterval != 100 {
|
||||
if options.Spec.Raft.SnapshotInterval != 100 {
|
||||
return client.SwarmUpdateResult{}, errors.New("snapshotInterval not correctly set")
|
||||
}
|
||||
if !options.Swarm.EncryptionConfig.AutoLockManagers {
|
||||
if !options.Spec.EncryptionConfig.AutoLockManagers {
|
||||
return client.SwarmUpdateResult{}, errors.New("auto-lock not correctly set")
|
||||
}
|
||||
return client.SwarmUpdateResult{}, nil
|
||||
@ -159,7 +159,7 @@ func TestSwarmUpdate(t *testing.T) {
|
||||
flagAutolock: "true",
|
||||
},
|
||||
swarmUpdateFunc: func(options client.SwarmUpdateOptions) (client.SwarmUpdateResult, error) {
|
||||
if *options.Swarm.Orchestration.TaskHistoryRetentionLimit != 10 {
|
||||
if *options.Spec.Orchestration.TaskHistoryRetentionLimit != 10 {
|
||||
return client.SwarmUpdateResult{}, errors.New("historyLimit not correctly set")
|
||||
}
|
||||
return client.SwarmUpdateResult{}, nil
|
||||
|
||||
@ -309,8 +309,8 @@ func volumeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []s
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
names := make([]string, 0, len(res.Items.Volumes))
|
||||
for _, v := range res.Items.Volumes {
|
||||
names := make([]string, 0, len(res.Items))
|
||||
for _, v := range res.Items {
|
||||
names = append(names, v.Name)
|
||||
}
|
||||
return names
|
||||
|
||||
@ -139,11 +139,9 @@ func TestCompleteEventFilter(t *testing.T) {
|
||||
client: &fakeClient{
|
||||
volumeListFunc: func(ctx context.Context, options client.VolumeListOptions) (client.VolumeListResult, error) {
|
||||
return client.VolumeListResult{
|
||||
Items: volume.ListResponse{
|
||||
Volumes: []*volume.Volume{
|
||||
builders.Volume(builders.VolumeName("v1")),
|
||||
builders.Volume(builders.VolumeName("v2")),
|
||||
},
|
||||
Items: []volume.Volume{
|
||||
builders.Volume(builders.VolumeName("v1")),
|
||||
builders.Volume(builders.VolumeName("v2")),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
@ -84,7 +84,7 @@ func TestVolumeInspectWithoutFormat(t *testing.T) {
|
||||
return client.VolumeInspectResult{}, fmt.Errorf("invalid volumeID, expected %s, got %s", "foo", volumeID)
|
||||
}
|
||||
return client.VolumeInspectResult{
|
||||
Volume: *builders.Volume(),
|
||||
Volume: builders.Volume(),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
@ -93,7 +93,7 @@ func TestVolumeInspectWithoutFormat(t *testing.T) {
|
||||
args: []string{"foo", "bar"},
|
||||
volumeInspectFunc: func(volumeID string) (client.VolumeInspectResult, error) {
|
||||
return client.VolumeInspectResult{
|
||||
Volume: *builders.Volume(builders.VolumeName(volumeID), builders.VolumeLabels(map[string]string{
|
||||
Volume: builders.Volume(builders.VolumeName(volumeID), builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
}, nil
|
||||
@ -114,7 +114,7 @@ func TestVolumeInspectWithoutFormat(t *testing.T) {
|
||||
func TestVolumeInspectWithFormat(t *testing.T) {
|
||||
volumeInspectFunc := func(volumeID string) (client.VolumeInspectResult, error) {
|
||||
return client.VolumeInspectResult{
|
||||
Volume: *builders.Volume(builders.VolumeLabels(map[string]string{
|
||||
Volume: builders.Volume(builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
}, nil
|
||||
|
||||
@ -71,13 +71,13 @@ func runList(ctx context.Context, dockerCLI command.Cli, options listOptions) er
|
||||
|
||||
// trick for filtering in place
|
||||
n := 0
|
||||
for _, vol := range res.Items.Volumes {
|
||||
for _, vol := range res.Items {
|
||||
if vol.ClusterVolume != nil {
|
||||
res.Items.Volumes[n] = vol
|
||||
res.Items[n] = vol
|
||||
n++
|
||||
}
|
||||
}
|
||||
res.Items.Volumes = res.Items.Volumes[:n]
|
||||
res.Items = res.Items[:n]
|
||||
if !options.quiet {
|
||||
format = clusterTableFormat
|
||||
} else {
|
||||
@ -85,13 +85,13 @@ func runList(ctx context.Context, dockerCLI command.Cli, options listOptions) er
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(res.Items.Volumes, func(i, j int) bool {
|
||||
return sortorder.NaturalLess(res.Items.Volumes[i].Name, res.Items.Volumes[j].Name)
|
||||
sort.Slice(res.Items, func(i, j int) bool {
|
||||
return sortorder.NaturalLess(res.Items[i].Name, res.Items[j].Name)
|
||||
})
|
||||
|
||||
volumeCtx := formatter.Context{
|
||||
Output: dockerCLI.Out(),
|
||||
Format: formatter.NewVolumeFormat(format, options.quiet),
|
||||
}
|
||||
return formatter.VolumeWrite(volumeCtx, res.Items.Volumes)
|
||||
return formatter.VolumeWrite(volumeCtx, res.Items)
|
||||
}
|
||||
|
||||
@ -52,14 +52,12 @@ func TestVolumeListWithoutFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) {
|
||||
return client.VolumeListResult{
|
||||
Items: volume.ListResponse{
|
||||
Volumes: []*volume.Volume{
|
||||
builders.Volume(),
|
||||
builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")),
|
||||
builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
},
|
||||
Items: []volume.Volume{
|
||||
builders.Volume(),
|
||||
builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")),
|
||||
builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
@ -73,14 +71,12 @@ func TestVolumeListWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) {
|
||||
return client.VolumeListResult{
|
||||
Items: volume.ListResponse{
|
||||
Volumes: []*volume.Volume{
|
||||
builders.Volume(),
|
||||
builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")),
|
||||
builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
},
|
||||
Items: []volume.Volume{
|
||||
builders.Volume(),
|
||||
builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")),
|
||||
builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
@ -97,14 +93,12 @@ func TestVolumeListWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) {
|
||||
return client.VolumeListResult{
|
||||
Items: volume.ListResponse{
|
||||
Volumes: []*volume.Volume{
|
||||
builders.Volume(),
|
||||
builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")),
|
||||
builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
},
|
||||
Items: []volume.Volume{
|
||||
builders.Volume(),
|
||||
builders.Volume(builders.VolumeName("foo"), builders.VolumeDriver("bar")),
|
||||
builders.Volume(builders.VolumeName("baz"), builders.VolumeLabels(map[string]string{
|
||||
"foo": "bar",
|
||||
})),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
@ -119,12 +113,10 @@ func TestVolumeListSortOrder(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) {
|
||||
return client.VolumeListResult{
|
||||
Items: volume.ListResponse{
|
||||
Volumes: []*volume.Volume{
|
||||
builders.Volume(builders.VolumeName("volume-2-foo")),
|
||||
builders.Volume(builders.VolumeName("volume-10-foo")),
|
||||
builders.Volume(builders.VolumeName("volume-1-foo")),
|
||||
},
|
||||
Items: []volume.Volume{
|
||||
builders.Volume(builders.VolumeName("volume-2-foo")),
|
||||
builders.Volume(builders.VolumeName("volume-10-foo")),
|
||||
builders.Volume(builders.VolumeName("volume-1-foo")),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
@ -139,101 +131,99 @@ func TestClusterVolumeList(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
volumeListFunc: func(client.VolumeListOptions) (client.VolumeListResult, error) {
|
||||
return client.VolumeListResult{
|
||||
Items: volume.ListResponse{
|
||||
Volumes: []*volume.Volume{
|
||||
{
|
||||
Name: "volume1",
|
||||
Scope: "global",
|
||||
Driver: "driver1",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group1",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeSingleNode,
|
||||
Sharing: volume.SharingOneWriter,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityActive,
|
||||
Items: []volume.Volume{
|
||||
{
|
||||
Name: "volume1",
|
||||
Scope: "global",
|
||||
Driver: "driver1",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group1",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeSingleNode,
|
||||
Sharing: volume.SharingOneWriter,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityActive,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "volume2",
|
||||
Scope: "global",
|
||||
Driver: "driver1",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group1",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeSingleNode,
|
||||
Sharing: volume.SharingOneWriter,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityPause,
|
||||
},
|
||||
Info: &volume.Info{
|
||||
CapacityBytes: 100000000,
|
||||
VolumeID: "driver1vol2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "volume3",
|
||||
Scope: "global",
|
||||
Driver: "driver2",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group2",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeMultiNode,
|
||||
Sharing: volume.SharingAll,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityActive,
|
||||
},
|
||||
PublishStatus: []*volume.PublishStatus{
|
||||
{
|
||||
NodeID: "nodeid1",
|
||||
State: volume.StatePublished,
|
||||
},
|
||||
},
|
||||
Info: &volume.Info{
|
||||
CapacityBytes: 100000000,
|
||||
VolumeID: "driver1vol3",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "volume4",
|
||||
Scope: "global",
|
||||
Driver: "driver2",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group2",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeMultiNode,
|
||||
Sharing: volume.SharingAll,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityActive,
|
||||
},
|
||||
PublishStatus: []*volume.PublishStatus{
|
||||
{
|
||||
NodeID: "nodeid1",
|
||||
State: volume.StatePublished,
|
||||
}, {
|
||||
NodeID: "nodeid2",
|
||||
State: volume.StatePublished,
|
||||
},
|
||||
},
|
||||
Info: &volume.Info{
|
||||
CapacityBytes: 100000000,
|
||||
VolumeID: "driver1vol4",
|
||||
},
|
||||
},
|
||||
},
|
||||
builders.Volume(builders.VolumeName("volume-local-1")),
|
||||
},
|
||||
{
|
||||
Name: "volume2",
|
||||
Scope: "global",
|
||||
Driver: "driver1",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group1",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeSingleNode,
|
||||
Sharing: volume.SharingOneWriter,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityPause,
|
||||
},
|
||||
Info: &volume.Info{
|
||||
CapacityBytes: 100000000,
|
||||
VolumeID: "driver1vol2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "volume3",
|
||||
Scope: "global",
|
||||
Driver: "driver2",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group2",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeMultiNode,
|
||||
Sharing: volume.SharingAll,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityActive,
|
||||
},
|
||||
PublishStatus: []*volume.PublishStatus{
|
||||
{
|
||||
NodeID: "nodeid1",
|
||||
State: volume.StatePublished,
|
||||
},
|
||||
},
|
||||
Info: &volume.Info{
|
||||
CapacityBytes: 100000000,
|
||||
VolumeID: "driver1vol3",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "volume4",
|
||||
Scope: "global",
|
||||
Driver: "driver2",
|
||||
ClusterVolume: &volume.ClusterVolume{
|
||||
Spec: volume.ClusterVolumeSpec{
|
||||
Group: "group2",
|
||||
AccessMode: &volume.AccessMode{
|
||||
Scope: volume.ScopeMultiNode,
|
||||
Sharing: volume.SharingAll,
|
||||
MountVolume: &volume.TypeMount{},
|
||||
},
|
||||
Availability: volume.AvailabilityActive,
|
||||
},
|
||||
PublishStatus: []*volume.PublishStatus{
|
||||
{
|
||||
NodeID: "nodeid1",
|
||||
State: volume.StatePublished,
|
||||
}, {
|
||||
NodeID: "nodeid2",
|
||||
State: volume.StatePublished,
|
||||
},
|
||||
},
|
||||
Info: &volume.Info{
|
||||
CapacityBytes: 100000000,
|
||||
VolumeID: "driver1vol4",
|
||||
},
|
||||
},
|
||||
},
|
||||
builders.Volume(builders.VolumeName("volume-local-1")),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
@ -26,7 +26,7 @@ import (
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
"github.com/google/shlex"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
"github.com/moby/moby/api/types/versions"
|
||||
"github.com/moby/moby/client/pkg/versions"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@ -20,7 +20,7 @@ import (
|
||||
cliflags "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/cli/cli/version"
|
||||
platformsignals "github.com/docker/cli/cmd/docker/internal/signals"
|
||||
"github.com/moby/moby/api/types/versions"
|
||||
"github.com/moby/moby/client/pkg/versions"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
"github.com/creack/pty"
|
||||
"github.com/docker/cli/e2e/internal/fixtures"
|
||||
"github.com/docker/cli/internal/test/environment"
|
||||
"github.com/moby/moby/api/types/versions"
|
||||
"github.com/moby/moby/client/pkg/versions"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/golden"
|
||||
|
||||
@ -4,8 +4,8 @@ import "github.com/moby/moby/api/types/volume"
|
||||
|
||||
// Volume creates a volume with default values.
|
||||
// Any number of volume function builder can be passed to augment it.
|
||||
func Volume(builders ...func(vol *volume.Volume)) *volume.Volume {
|
||||
vol := &volume.Volume{
|
||||
func Volume(builders ...func(vol *volume.Volume)) volume.Volume {
|
||||
vol := volume.Volume{
|
||||
Name: "volume",
|
||||
Driver: "local",
|
||||
Mountpoint: "/data/volume",
|
||||
@ -13,7 +13,7 @@ func Volume(builders ...func(vol *volume.Volume)) *volume.Volume {
|
||||
}
|
||||
|
||||
for _, builder := range builders {
|
||||
builder(vol)
|
||||
builder(&vol)
|
||||
}
|
||||
|
||||
return vol
|
||||
|
||||
@ -28,8 +28,8 @@ require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/mattn/go-runewidth v0.0.17
|
||||
github.com/moby/go-archive v0.1.0
|
||||
github.com/moby/moby/api v1.52.0-beta.2.0.20251023134003-dcd668d5796b // master
|
||||
github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b // master
|
||||
github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825 // master
|
||||
github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825 // master
|
||||
github.com/moby/patternmatcher v0.6.0
|
||||
github.com/moby/swarmkit/v2 v2.1.0
|
||||
github.com/moby/sys/atomicwriter v0.1.0
|
||||
|
||||
@ -170,10 +170,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
||||
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
|
||||
github.com/moby/moby/api v1.52.0-beta.2.0.20251023134003-dcd668d5796b h1:2y00KCjD3Dt6CFi8Zr7kh0ew32S2784EWbyKAXqQw2Q=
|
||||
github.com/moby/moby/api v1.52.0-beta.2.0.20251023134003-dcd668d5796b/go.mod h1:/ou52HkRydg4+odrUR3vFsGgjIyHvprrpEQEkweL10s=
|
||||
github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b h1:+JMltOoDeSwWJv4AMXE9e3dSe1h4LD4+bt6tqNO5h0s=
|
||||
github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b/go.mod h1:sxVfwGqVgh7n+tdxA4gFToQ/lf+bM7zATnvQjVnsKT4=
|
||||
github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825 h1:hIQtHzNpFguJCWlgZ4z9L83YjLYpf9uP9+3cSYXP9hg=
|
||||
github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825/go.mod h1:/ou52HkRydg4+odrUR3vFsGgjIyHvprrpEQEkweL10s=
|
||||
github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825 h1:7kbhU8foMePfI9vB24bSld1RzJQpbquW8sZarquRHbY=
|
||||
github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825/go.mod h1:sxVfwGqVgh7n+tdxA4gFToQ/lf+bM7zATnvQjVnsKT4=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/swarmkit/v2 v2.1.0 h1:u+cJ5hSyF3HnzsyI+NtegYxdIPQIuibk7IbpXNxuISM=
|
||||
|
||||
11
vendor/github.com/moby/moby/api/types/swarm/task.go
generated
vendored
11
vendor/github.com/moby/moby/api/types/swarm/task.go
generated
vendored
@ -138,6 +138,17 @@ type DiscreteGenericResource struct {
|
||||
type ResourceRequirements struct {
|
||||
Limits *Limit `json:",omitempty"`
|
||||
Reservations *Resources `json:",omitempty"`
|
||||
|
||||
// Amount of swap in bytes - can only be used together with a memory limit
|
||||
// -1 means unlimited
|
||||
// a null pointer keeps the default behaviour of granting twice the memory
|
||||
// amount in swap
|
||||
SwapBytes *int64 `json:"SwapBytes,omitzero"`
|
||||
|
||||
// Tune container memory swappiness (0 to 100) - if not specified, defaults
|
||||
// to the container OS's default - generally 60, or the value predefined in
|
||||
// the image; set to -1 to unset a previously set value
|
||||
MemorySwappiness *int64 `json:MemorySwappiness,omitzero"`
|
||||
}
|
||||
|
||||
// Placement represents orchestration parameters.
|
||||
|
||||
2
vendor/github.com/moby/moby/client/build_prune.go
generated
vendored
2
vendor/github.com/moby/moby/client/build_prune.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/moby/moby/api/types/build"
|
||||
"github.com/moby/moby/api/types/versions"
|
||||
"github.com/moby/moby/client/pkg/versions"
|
||||
)
|
||||
|
||||
// BuildCachePruneOptions hold parameters to prune the build cache.
|
||||
|
||||
2
vendor/github.com/moby/moby/client/client.go
generated
vendored
2
vendor/github.com/moby/moby/client/client.go
generated
vendored
@ -56,7 +56,7 @@ import (
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/moby/moby/api/types/versions"
|
||||
"github.com/moby/moby/client/pkg/versions"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
)
|
||||
|
||||
|
||||
15
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
15
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
@ -12,7 +12,6 @@ import (
|
||||
"github.com/moby/moby/api/types/registry"
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
"github.com/moby/moby/api/types/system"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// APIClient is an interface that clients that talk with a docker server must implement.
|
||||
@ -58,10 +57,10 @@ type HijackDialer interface {
|
||||
|
||||
// ContainerAPIClient defines API client methods for the containers
|
||||
type ContainerAPIClient interface {
|
||||
ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (HijackedResponse, error)
|
||||
ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (container.CommitResponse, error)
|
||||
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error)
|
||||
ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error)
|
||||
ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (ContainerAttachResult, error)
|
||||
ContainerCommit(ctx context.Context, container string, options ContainerCommitOptions) (ContainerCommitResult, error)
|
||||
ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error)
|
||||
ContainerDiff(ctx context.Context, container string, options ContainerDiffOptions) (ContainerDiffResult, error)
|
||||
ExecAPIClient
|
||||
ContainerExport(ctx context.Context, container string) (io.ReadCloser, error)
|
||||
ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error)
|
||||
@ -158,11 +157,11 @@ type PluginAPIClient interface {
|
||||
|
||||
// ServiceAPIClient defines API client methods for the services
|
||||
type ServiceAPIClient interface {
|
||||
ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options ServiceCreateOptions) (ServiceCreateResult, error)
|
||||
ServiceCreate(ctx context.Context, options ServiceCreateOptions) (ServiceCreateResult, error)
|
||||
ServiceInspect(ctx context.Context, serviceID string, options ServiceInspectOptions) (ServiceInspectResult, error)
|
||||
ServiceList(ctx context.Context, options ServiceListOptions) (ServiceListResult, error)
|
||||
ServiceRemove(ctx context.Context, serviceID string, options ServiceRemoveOptions) (ServiceRemoveResult, error)
|
||||
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options ServiceUpdateOptions) (ServiceUpdateResult, error)
|
||||
ServiceUpdate(ctx context.Context, serviceID string, options ServiceUpdateOptions) (ServiceUpdateResult, error)
|
||||
ServiceLogs(ctx context.Context, serviceID string, options ServiceLogsOptions) (ServiceLogsResult, error)
|
||||
TaskLogs(ctx context.Context, taskID string, options TaskLogsOptions) (TaskLogsResult, error)
|
||||
TaskInspect(ctx context.Context, taskID string, options TaskInspectOptions) (TaskInspectResult, error)
|
||||
@ -177,7 +176,7 @@ type SwarmAPIClient interface {
|
||||
SwarmUnlock(ctx context.Context, options SwarmUnlockOptions) (SwarmUnlockResult, error)
|
||||
SwarmLeave(ctx context.Context, options SwarmLeaveOptions) (SwarmLeaveResult, error)
|
||||
SwarmInspect(ctx context.Context, options SwarmInspectOptions) (SwarmInspectResult, error)
|
||||
SwarmUpdate(ctx context.Context, version swarm.Version, options SwarmUpdateOptions) (SwarmUpdateResult, error)
|
||||
SwarmUpdate(ctx context.Context, options SwarmUpdateOptions) (SwarmUpdateResult, error)
|
||||
}
|
||||
|
||||
// SystemAPIClient defines API client methods for the system
|
||||
|
||||
4
vendor/github.com/moby/moby/client/config_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/config_inspect.go
generated
vendored
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
)
|
||||
@ -14,7 +15,7 @@ type ConfigInspectOptions struct {
|
||||
// ConfigInspectResult holds the result from the ConfigInspect method.
|
||||
type ConfigInspectResult struct {
|
||||
Config swarm.Config
|
||||
Raw []byte
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// ConfigInspect returns the config information with raw data
|
||||
@ -24,7 +25,6 @@ func (cli *Client) ConfigInspect(ctx context.Context, id string, options ConfigI
|
||||
return ConfigInspectResult{}, err
|
||||
}
|
||||
resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ConfigInspectResult{}, err
|
||||
}
|
||||
|
||||
16
vendor/github.com/moby/moby/client/container_attach.go
generated
vendored
16
vendor/github.com/moby/moby/client/container_attach.go
generated
vendored
@ -16,6 +16,11 @@ type ContainerAttachOptions struct {
|
||||
Logs bool
|
||||
}
|
||||
|
||||
// ContainerAttachResult is the result from attaching to a container.
|
||||
type ContainerAttachResult struct {
|
||||
HijackedResponse
|
||||
}
|
||||
|
||||
// ContainerAttach attaches a connection to a container in the server.
|
||||
// It returns a [HijackedResponse] with the hijacked connection
|
||||
// and a reader to get output. It's up to the called to close
|
||||
@ -44,10 +49,10 @@ type ContainerAttachOptions struct {
|
||||
// [stdcopy.StdType]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#StdType
|
||||
// [Stdout]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stdout
|
||||
// [Stderr]: https://pkg.go.dev/github.com/moby/moby/api/pkg/stdcopy#Stderr
|
||||
func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (HijackedResponse, error) {
|
||||
func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options ContainerAttachOptions) (ContainerAttachResult, error) {
|
||||
containerID, err := trimID("container", containerID)
|
||||
if err != nil {
|
||||
return HijackedResponse{}, err
|
||||
return ContainerAttachResult{}, err
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
@ -70,7 +75,12 @@ func (cli *Client) ContainerAttach(ctx context.Context, containerID string, opti
|
||||
query.Set("logs", "1")
|
||||
}
|
||||
|
||||
return cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{
|
||||
hijacked, err := cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{
|
||||
"Content-Type": {"text/plain"},
|
||||
})
|
||||
if err != nil {
|
||||
return ContainerAttachResult{}, err
|
||||
}
|
||||
|
||||
return ContainerAttachResult{HijackedResponse: hijacked}, nil
|
||||
}
|
||||
|
||||
17
vendor/github.com/moby/moby/client/container_commit.go
generated
vendored
17
vendor/github.com/moby/moby/client/container_commit.go
generated
vendored
@ -20,22 +20,27 @@ type ContainerCommitOptions struct {
|
||||
Config *container.Config
|
||||
}
|
||||
|
||||
// ContainerCommitResult is the result from committing a container.
|
||||
type ContainerCommitResult struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// ContainerCommit applies changes to a container and creates a new tagged image.
|
||||
func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (container.CommitResponse, error) {
|
||||
func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options ContainerCommitOptions) (ContainerCommitResult, error) {
|
||||
containerID, err := trimID("container", containerID)
|
||||
if err != nil {
|
||||
return container.CommitResponse{}, err
|
||||
return ContainerCommitResult{}, err
|
||||
}
|
||||
|
||||
var repository, tag string
|
||||
if options.Reference != "" {
|
||||
ref, err := reference.ParseNormalizedNamed(options.Reference)
|
||||
if err != nil {
|
||||
return container.CommitResponse{}, err
|
||||
return ContainerCommitResult{}, err
|
||||
}
|
||||
|
||||
if _, ok := ref.(reference.Digested); ok {
|
||||
return container.CommitResponse{}, errors.New("refusing to create a tag with a digest reference")
|
||||
return ContainerCommitResult{}, errors.New("refusing to create a tag with a digest reference")
|
||||
}
|
||||
ref = reference.TagNameOnly(ref)
|
||||
|
||||
@ -62,9 +67,9 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti
|
||||
resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return response, err
|
||||
return ContainerCommitResult{}, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||
return response, err
|
||||
return ContainerCommitResult{ID: response.ID}, err
|
||||
}
|
||||
|
||||
46
vendor/github.com/moby/moby/client/container_create.go
generated
vendored
46
vendor/github.com/moby/moby/client/container_create.go
generated
vendored
@ -10,49 +10,63 @@ import (
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// ContainerCreate creates a new container based on the given configuration.
|
||||
// It can be associated with a name, but it's not mandatory.
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
|
||||
if config == nil {
|
||||
return container.CreateResponse{}, cerrdefs.ErrInvalidArgument.WithMessage("config is nil")
|
||||
func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateOptions) (ContainerCreateResult, error) {
|
||||
cfg := options.Config
|
||||
|
||||
if cfg == nil {
|
||||
cfg = &container.Config{}
|
||||
}
|
||||
|
||||
if options.Image != "" {
|
||||
if cfg.Image != "" {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("either Image or config.Image should be set")
|
||||
}
|
||||
newCfg := *cfg
|
||||
newCfg.Image = options.Image
|
||||
cfg = &newCfg
|
||||
}
|
||||
|
||||
if cfg.Image == "" {
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config.Image or Image is required")
|
||||
}
|
||||
|
||||
var response container.CreateResponse
|
||||
|
||||
if hostConfig != nil {
|
||||
hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd)
|
||||
hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop)
|
||||
if options.HostConfig != nil {
|
||||
options.HostConfig.CapAdd = normalizeCapabilities(options.HostConfig.CapAdd)
|
||||
options.HostConfig.CapDrop = normalizeCapabilities(options.HostConfig.CapDrop)
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
if platform != nil {
|
||||
if p := formatPlatform(*platform); p != "unknown" {
|
||||
if options.Platform != nil {
|
||||
if p := formatPlatform(*options.Platform); p != "unknown" {
|
||||
query.Set("platform", p)
|
||||
}
|
||||
}
|
||||
|
||||
if containerName != "" {
|
||||
query.Set("name", containerName)
|
||||
if options.Name != "" {
|
||||
query.Set("name", options.Name)
|
||||
}
|
||||
|
||||
body := container.CreateRequest{
|
||||
Config: config,
|
||||
HostConfig: hostConfig,
|
||||
NetworkingConfig: networkingConfig,
|
||||
Config: cfg,
|
||||
HostConfig: options.HostConfig,
|
||||
NetworkingConfig: options.NetworkingConfig,
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/create", query, body, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return response, err
|
||||
return ContainerCreateResult{}, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||
return response, err
|
||||
return ContainerCreateResult{ID: response.ID, Warnings: response.Warnings}, err
|
||||
}
|
||||
|
||||
// formatPlatform returns a formatted string representing platform (e.g., "linux/arm/v7").
|
||||
|
||||
25
vendor/github.com/moby/moby/client/container_create_opts.go
generated
vendored
Normal file
25
vendor/github.com/moby/moby/client/container_create_opts.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// ContainerCreateOptions holds parameters to create a container.
|
||||
type ContainerCreateOptions struct {
|
||||
Config *container.Config
|
||||
HostConfig *container.HostConfig
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
Platform *ocispec.Platform
|
||||
Name string
|
||||
|
||||
// Image is a shortcut for Config.Image - only one of Image or Config.Image should be set.
|
||||
Image string
|
||||
}
|
||||
|
||||
// ContainerCreateResult is the result from creating a container.
|
||||
type ContainerCreateResult struct {
|
||||
ID string
|
||||
Warnings []string
|
||||
}
|
||||
10
vendor/github.com/moby/moby/client/container_diff.go
generated
vendored
10
vendor/github.com/moby/moby/client/container_diff.go
generated
vendored
@ -9,22 +9,22 @@ import (
|
||||
)
|
||||
|
||||
// ContainerDiff shows differences in a container filesystem since it was started.
|
||||
func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) {
|
||||
func (cli *Client) ContainerDiff(ctx context.Context, containerID string, options ContainerDiffOptions) (ContainerDiffResult, error) {
|
||||
containerID, err := trimID("container", containerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ContainerDiffResult{}, err
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ContainerDiffResult{}, err
|
||||
}
|
||||
|
||||
var changes []container.FilesystemChange
|
||||
err = json.NewDecoder(resp.Body).Decode(&changes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ContainerDiffResult{}, err
|
||||
}
|
||||
return changes, err
|
||||
return ContainerDiffResult{Changes: changes}, err
|
||||
}
|
||||
|
||||
13
vendor/github.com/moby/moby/client/container_diff_opts.go
generated
vendored
Normal file
13
vendor/github.com/moby/moby/client/container_diff_opts.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package client
|
||||
|
||||
import "github.com/moby/moby/api/types/container"
|
||||
|
||||
// ContainerDiffOptions holds parameters to show differences in a container filesystem.
|
||||
type ContainerDiffOptions struct {
|
||||
// Currently no options, but this allows for future extensibility
|
||||
}
|
||||
|
||||
// ContainerDiffResult is the result from showing differences in a container filesystem.
|
||||
type ContainerDiffResult struct {
|
||||
Changes []container.FilesystemChange
|
||||
}
|
||||
35
vendor/github.com/moby/moby/client/container_exec.go
generated
vendored
35
vendor/github.com/moby/moby/client/container_exec.go
generated
vendored
@ -26,7 +26,7 @@ type ExecCreateOptions struct {
|
||||
|
||||
// ExecCreateResult holds the result of creating a container exec.
|
||||
type ExecCreateResult struct {
|
||||
container.ExecCreateResponse
|
||||
ID string
|
||||
}
|
||||
|
||||
// ExecCreate creates a new exec configuration to run an exec process.
|
||||
@ -58,7 +58,7 @@ func (cli *Client) ExecCreate(ctx context.Context, containerID string, options E
|
||||
|
||||
var response container.ExecCreateResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||
return ExecCreateResult{ExecCreateResponse: response}, err
|
||||
return ExecCreateResult{ID: response.ID}, err
|
||||
}
|
||||
|
||||
type execStartAttachOptions struct {
|
||||
@ -127,26 +127,21 @@ func (cli *Client) ExecAttach(ctx context.Context, execID string, options ExecAt
|
||||
return ExecAttachResult{HijackedResponse: response}, err
|
||||
}
|
||||
|
||||
// ExecInspect holds information returned by exec inspect.
|
||||
//
|
||||
// It provides a subset of the information included in [container.ExecInspectResponse].
|
||||
//
|
||||
// TODO(thaJeztah): include all fields of [container.ExecInspectResponse] ?
|
||||
type ExecInspect struct {
|
||||
ExecID string `json:"ID"`
|
||||
ContainerID string `json:"ContainerID"`
|
||||
Running bool `json:"Running"`
|
||||
ExitCode int `json:"ExitCode"`
|
||||
Pid int `json:"Pid"`
|
||||
}
|
||||
|
||||
// ExecInspectOptions holds options for inspecting a container exec.
|
||||
type ExecInspectOptions struct {
|
||||
}
|
||||
|
||||
// ExecInspectResult holds the result of inspecting a container exec.
|
||||
//
|
||||
// It provides a subset of the information included in [container.ExecInspectResponse].
|
||||
//
|
||||
// TODO(thaJeztah): include all fields of [container.ExecInspectResponse] ?
|
||||
type ExecInspectResult struct {
|
||||
ExecInspect
|
||||
ID string
|
||||
ContainerID string
|
||||
Running bool
|
||||
ExitCode int
|
||||
PID int
|
||||
}
|
||||
|
||||
// ExecInspect returns information about a specific exec process on the docker host.
|
||||
@ -168,11 +163,11 @@ func (cli *Client) ExecInspect(ctx context.Context, execID string, options ExecI
|
||||
ec = *response.ExitCode
|
||||
}
|
||||
|
||||
return ExecInspectResult{ExecInspect: ExecInspect{
|
||||
ExecID: response.ID,
|
||||
return ExecInspectResult{
|
||||
ID: response.ID,
|
||||
ContainerID: response.ContainerID,
|
||||
Running: response.Running,
|
||||
ExitCode: ec,
|
||||
Pid: response.Pid,
|
||||
}}, nil
|
||||
PID: response.Pid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
2
vendor/github.com/moby/moby/client/errors.go
generated
vendored
2
vendor/github.com/moby/moby/client/errors.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/errdefs/pkg/errhttp"
|
||||
"github.com/moby/moby/api/types/versions"
|
||||
"github.com/moby/moby/client/pkg/versions"
|
||||
)
|
||||
|
||||
// errConnectionFailed implements an error returned when connection failed.
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_import.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_import.go
generated
vendored
@ -42,5 +42,5 @@ func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, re
|
||||
if err != nil {
|
||||
return ImageImportResult{}, err
|
||||
}
|
||||
return ImageImportResult{body: resp.Body}, nil
|
||||
return ImageImportResult{rc: resp.Body}, nil
|
||||
}
|
||||
|
||||
11
vendor/github.com/moby/moby/client/image_import_opts.go
generated
vendored
11
vendor/github.com/moby/moby/client/image_import_opts.go
generated
vendored
@ -20,16 +20,19 @@ type ImageImportOptions struct {
|
||||
|
||||
// ImageImportResult holds the response body returned by the daemon for image import.
|
||||
type ImageImportResult struct {
|
||||
body io.ReadCloser
|
||||
rc io.ReadCloser
|
||||
}
|
||||
|
||||
func (r ImageImportResult) Read(p []byte) (n int, err error) {
|
||||
return r.body.Read(p)
|
||||
if r.rc == nil {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return r.rc.Read(p)
|
||||
}
|
||||
|
||||
func (r ImageImportResult) Close() error {
|
||||
if r.body == nil {
|
||||
if r.rc == nil {
|
||||
return nil
|
||||
}
|
||||
return r.body.Close()
|
||||
return r.rc.Close()
|
||||
}
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_list.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_list.go
generated
vendored
@ -6,7 +6,7 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/moby/moby/api/types/image"
|
||||
"github.com/moby/moby/api/types/versions"
|
||||
"github.com/moby/moby/client/pkg/versions"
|
||||
)
|
||||
|
||||
// ImageList returns a list of images in the docker host.
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_remove.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_remove.go
generated
vendored
@ -35,5 +35,5 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options Imag
|
||||
|
||||
var dels []image.DeleteResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&dels)
|
||||
return ImageRemoveResult{Deleted: dels}, err
|
||||
return ImageRemoveResult{Items: dels}, err
|
||||
}
|
||||
|
||||
2
vendor/github.com/moby/moby/client/image_remove_opts.go
generated
vendored
2
vendor/github.com/moby/moby/client/image_remove_opts.go
generated
vendored
@ -14,5 +14,5 @@ type ImageRemoveOptions struct {
|
||||
|
||||
// ImageRemoveResult holds the delete responses returned by the daemon.
|
||||
type ImageRemoveResult struct {
|
||||
Deleted []image.DeleteResponse
|
||||
Items []image.DeleteResponse
|
||||
}
|
||||
|
||||
4
vendor/github.com/moby/moby/client/network_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/network_inspect.go
generated
vendored
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"github.com/moby/moby/api/types/network"
|
||||
@ -10,7 +11,7 @@ import (
|
||||
// NetworkInspectResult contains the result of a network inspection.
|
||||
type NetworkInspectResult struct {
|
||||
Network network.Inspect
|
||||
Raw []byte
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// NetworkInspect returns the information for a specific network configured in the docker host.
|
||||
@ -28,7 +29,6 @@ func (cli *Client) NetworkInspect(ctx context.Context, networkID string, options
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/networks/"+networkID, query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return NetworkInspectResult{}, err
|
||||
}
|
||||
|
||||
5
vendor/github.com/moby/moby/client/node_inspect.go
generated
vendored
5
vendor/github.com/moby/moby/client/node_inspect.go
generated
vendored
@ -9,9 +9,12 @@ import (
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
)
|
||||
|
||||
// NodeInspectOptions holds parameters to inspect nodes with.
|
||||
type NodeInspectOptions struct{}
|
||||
|
||||
type NodeInspectResult struct {
|
||||
Node swarm.Node
|
||||
Raw []byte
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// NodeInspect returns the node information.
|
||||
|
||||
5
vendor/github.com/moby/moby/client/node_list.go
generated
vendored
5
vendor/github.com/moby/moby/client/node_list.go
generated
vendored
@ -8,6 +8,11 @@ import (
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
)
|
||||
|
||||
// NodeListOptions holds parameters to list nodes with.
|
||||
type NodeListOptions struct {
|
||||
Filters Filters
|
||||
}
|
||||
|
||||
type NodeListResult struct {
|
||||
Items []swarm.Node
|
||||
}
|
||||
|
||||
4
vendor/github.com/moby/moby/client/node_remove.go
generated
vendored
4
vendor/github.com/moby/moby/client/node_remove.go
generated
vendored
@ -5,6 +5,10 @@ import (
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// NodeRemoveOptions holds parameters to remove nodes with.
|
||||
type NodeRemoveOptions struct {
|
||||
Force bool
|
||||
}
|
||||
type NodeRemoveResult struct{}
|
||||
|
||||
// NodeRemove removes a Node.
|
||||
|
||||
10
vendor/github.com/moby/moby/client/node_update.go
generated
vendored
10
vendor/github.com/moby/moby/client/node_update.go
generated
vendored
@ -3,8 +3,16 @@ package client
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
)
|
||||
|
||||
// NodeUpdateOptions holds parameters to update nodes with.
|
||||
type NodeUpdateOptions struct {
|
||||
Version swarm.Version
|
||||
Spec swarm.NodeSpec
|
||||
}
|
||||
|
||||
type NodeUpdateResult struct{}
|
||||
|
||||
// NodeUpdate updates a Node.
|
||||
@ -16,7 +24,7 @@ func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, options NodeUp
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("version", options.Version.String())
|
||||
resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, options.Node, nil)
|
||||
resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, options.Spec, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
return NodeUpdateResult{}, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/moby/moby/client/plugin_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/plugin_inspect.go
generated
vendored
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/moby/moby/api/types/plugin"
|
||||
)
|
||||
@ -13,8 +14,8 @@ type PluginInspectOptions struct {
|
||||
|
||||
// PluginInspectResult holds the result from the [Client.PluginInspect] method.
|
||||
type PluginInspectResult struct {
|
||||
Raw []byte
|
||||
Plugin plugin.Plugin
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// PluginInspect inspects an existing plugin
|
||||
@ -24,7 +25,6 @@ func (cli *Client) PluginInspect(ctx context.Context, name string, options Plugi
|
||||
return PluginInspectResult{}, err
|
||||
}
|
||||
resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return PluginInspectResult{}, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/moby/moby/client/secret_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/secret_inspect.go
generated
vendored
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
)
|
||||
@ -14,7 +15,7 @@ type SecretInspectOptions struct {
|
||||
// SecretInspectResult holds the result from the [Client.SecretInspect]. method.
|
||||
type SecretInspectResult struct {
|
||||
Secret swarm.Secret
|
||||
Raw []byte
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// SecretInspect returns the secret information with raw data.
|
||||
@ -24,7 +25,6 @@ func (cli *Client) SecretInspect(ctx context.Context, id string, options SecretI
|
||||
return SecretInspectResult{}, err
|
||||
}
|
||||
resp, err := cli.get(ctx, "/secrets/"+id, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return SecretInspectResult{}, err
|
||||
}
|
||||
|
||||
28
vendor/github.com/moby/moby/client/service_create.go
generated
vendored
28
vendor/github.com/moby/moby/client/service_create.go
generated
vendored
@ -16,6 +16,8 @@ import (
|
||||
|
||||
// ServiceCreateOptions contains the options to use when creating a service.
|
||||
type ServiceCreateOptions struct {
|
||||
Spec swarm.ServiceSpec
|
||||
|
||||
// EncodedRegistryAuth is the encoded registry authorization credentials to
|
||||
// use when updating the service.
|
||||
//
|
||||
@ -39,33 +41,33 @@ type ServiceCreateResult struct {
|
||||
}
|
||||
|
||||
// ServiceCreate creates a new service.
|
||||
func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options ServiceCreateOptions) (ServiceCreateResult, error) {
|
||||
func (cli *Client) ServiceCreate(ctx context.Context, options ServiceCreateOptions) (ServiceCreateResult, error) {
|
||||
// Make sure containerSpec is not nil when no runtime is set or the runtime is set to container
|
||||
if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) {
|
||||
service.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{}
|
||||
if options.Spec.TaskTemplate.ContainerSpec == nil && (options.Spec.TaskTemplate.Runtime == "" || options.Spec.TaskTemplate.Runtime == swarm.RuntimeContainer) {
|
||||
options.Spec.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{}
|
||||
}
|
||||
|
||||
if err := validateServiceSpec(service); err != nil {
|
||||
if err := validateServiceSpec(options.Spec); err != nil {
|
||||
return ServiceCreateResult{}, err
|
||||
}
|
||||
|
||||
// ensure that the image is tagged
|
||||
var warnings []string
|
||||
switch {
|
||||
case service.TaskTemplate.ContainerSpec != nil:
|
||||
if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
|
||||
service.TaskTemplate.ContainerSpec.Image = taggedImg
|
||||
case options.Spec.TaskTemplate.ContainerSpec != nil:
|
||||
if taggedImg := imageWithTagString(options.Spec.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
|
||||
options.Spec.TaskTemplate.ContainerSpec.Image = taggedImg
|
||||
}
|
||||
if options.QueryRegistry {
|
||||
resolveWarning := resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth)
|
||||
resolveWarning := resolveContainerSpecImage(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth)
|
||||
warnings = append(warnings, resolveWarning)
|
||||
}
|
||||
case service.TaskTemplate.PluginSpec != nil:
|
||||
if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" {
|
||||
service.TaskTemplate.PluginSpec.Remote = taggedImg
|
||||
case options.Spec.TaskTemplate.PluginSpec != nil:
|
||||
if taggedImg := imageWithTagString(options.Spec.TaskTemplate.PluginSpec.Remote); taggedImg != "" {
|
||||
options.Spec.TaskTemplate.PluginSpec.Remote = taggedImg
|
||||
}
|
||||
if options.QueryRegistry {
|
||||
resolveWarning := resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth)
|
||||
resolveWarning := resolvePluginSpecRemote(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth)
|
||||
warnings = append(warnings, resolveWarning)
|
||||
}
|
||||
}
|
||||
@ -74,7 +76,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
|
||||
}
|
||||
resp, err := cli.post(ctx, "/services/create", nil, service, headers)
|
||||
resp, err := cli.post(ctx, "/services/create", nil, options.Spec, headers)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ServiceCreateResult{}, err
|
||||
|
||||
4
vendor/github.com/moby/moby/client/service_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/service_inspect.go
generated
vendored
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
@ -16,7 +17,7 @@ type ServiceInspectOptions struct {
|
||||
// ServiceInspectResult represents the result of a service inspect operation.
|
||||
type ServiceInspectResult struct {
|
||||
Service swarm.Service
|
||||
Raw []byte
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// ServiceInspect retrieves detailed information about a specific service by its ID.
|
||||
@ -29,7 +30,6 @@ func (cli *Client) ServiceInspect(ctx context.Context, serviceID string, options
|
||||
query := url.Values{}
|
||||
query.Set("insertDefaults", fmt.Sprintf("%v", options.InsertDefaults))
|
||||
resp, err := cli.get(ctx, "/services/"+serviceID, query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ServiceInspectResult{}, err
|
||||
}
|
||||
|
||||
27
vendor/github.com/moby/moby/client/service_update.go
generated
vendored
27
vendor/github.com/moby/moby/client/service_update.go
generated
vendored
@ -12,6 +12,9 @@ import (
|
||||
|
||||
// ServiceUpdateOptions contains the options to be used for updating services.
|
||||
type ServiceUpdateOptions struct {
|
||||
Version swarm.Version
|
||||
Spec swarm.ServiceSpec
|
||||
|
||||
// EncodedRegistryAuth is the encoded registry authorization credentials to
|
||||
// use when updating the service.
|
||||
//
|
||||
@ -50,13 +53,13 @@ type ServiceUpdateResult struct {
|
||||
// conflicting writes. It must be the value as set *before* the update.
|
||||
// You can find this value in the [swarm.Service.Meta] field, which can
|
||||
// be found using [Client.ServiceInspectWithRaw].
|
||||
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options ServiceUpdateOptions) (ServiceUpdateResult, error) {
|
||||
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, options ServiceUpdateOptions) (ServiceUpdateResult, error) {
|
||||
serviceID, err := trimID("service", serviceID)
|
||||
if err != nil {
|
||||
return ServiceUpdateResult{}, err
|
||||
}
|
||||
|
||||
if err := validateServiceSpec(service); err != nil {
|
||||
if err := validateServiceSpec(options.Spec); err != nil {
|
||||
return ServiceUpdateResult{}, err
|
||||
}
|
||||
|
||||
@ -69,25 +72,25 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
|
||||
query.Set("rollback", options.Rollback)
|
||||
}
|
||||
|
||||
query.Set("version", version.String())
|
||||
query.Set("version", options.Version.String())
|
||||
|
||||
// ensure that the image is tagged
|
||||
var warnings []string
|
||||
switch {
|
||||
case service.TaskTemplate.ContainerSpec != nil:
|
||||
if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
|
||||
service.TaskTemplate.ContainerSpec.Image = taggedImg
|
||||
case options.Spec.TaskTemplate.ContainerSpec != nil:
|
||||
if taggedImg := imageWithTagString(options.Spec.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
|
||||
options.Spec.TaskTemplate.ContainerSpec.Image = taggedImg
|
||||
}
|
||||
if options.QueryRegistry {
|
||||
resolveWarning := resolveContainerSpecImage(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth)
|
||||
resolveWarning := resolveContainerSpecImage(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth)
|
||||
warnings = append(warnings, resolveWarning)
|
||||
}
|
||||
case service.TaskTemplate.PluginSpec != nil:
|
||||
if taggedImg := imageWithTagString(service.TaskTemplate.PluginSpec.Remote); taggedImg != "" {
|
||||
service.TaskTemplate.PluginSpec.Remote = taggedImg
|
||||
case options.Spec.TaskTemplate.PluginSpec != nil:
|
||||
if taggedImg := imageWithTagString(options.Spec.TaskTemplate.PluginSpec.Remote); taggedImg != "" {
|
||||
options.Spec.TaskTemplate.PluginSpec.Remote = taggedImg
|
||||
}
|
||||
if options.QueryRegistry {
|
||||
resolveWarning := resolvePluginSpecRemote(ctx, cli, &service.TaskTemplate, options.EncodedRegistryAuth)
|
||||
resolveWarning := resolvePluginSpecRemote(ctx, cli, &options.Spec.TaskTemplate, options.EncodedRegistryAuth)
|
||||
warnings = append(warnings, resolveWarning)
|
||||
}
|
||||
}
|
||||
@ -96,7 +99,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers.Set(registry.AuthHeader, options.EncodedRegistryAuth)
|
||||
}
|
||||
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
|
||||
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, options.Spec, headers)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ServiceUpdateResult{}, err
|
||||
|
||||
4
vendor/github.com/moby/moby/client/swarm_node_inspect_opts.go
generated
vendored
4
vendor/github.com/moby/moby/client/swarm_node_inspect_opts.go
generated
vendored
@ -1,4 +0,0 @@
|
||||
package client
|
||||
|
||||
// NodeInspectOptions holds parameters to inspect nodes with.
|
||||
type NodeInspectOptions struct{}
|
||||
6
vendor/github.com/moby/moby/client/swarm_node_list_opts.go
generated
vendored
6
vendor/github.com/moby/moby/client/swarm_node_list_opts.go
generated
vendored
@ -1,6 +0,0 @@
|
||||
package client
|
||||
|
||||
// NodeListOptions holds parameters to list nodes with.
|
||||
type NodeListOptions struct {
|
||||
Filters Filters
|
||||
}
|
||||
6
vendor/github.com/moby/moby/client/swarm_node_remove_opts.go
generated
vendored
6
vendor/github.com/moby/moby/client/swarm_node_remove_opts.go
generated
vendored
@ -1,6 +0,0 @@
|
||||
package client
|
||||
|
||||
// NodeRemoveOptions holds parameters to remove nodes with.
|
||||
type NodeRemoveOptions struct {
|
||||
Force bool
|
||||
}
|
||||
9
vendor/github.com/moby/moby/client/swarm_node_update_opts.go
generated
vendored
9
vendor/github.com/moby/moby/client/swarm_node_update_opts.go
generated
vendored
@ -1,9 +0,0 @@
|
||||
package client
|
||||
|
||||
import "github.com/moby/moby/api/types/swarm"
|
||||
|
||||
// NodeUpdateOptions holds parameters to update nodes with.
|
||||
type NodeUpdateOptions struct {
|
||||
Version swarm.Version
|
||||
Node swarm.NodeSpec
|
||||
}
|
||||
9
vendor/github.com/moby/moby/client/swarm_update.go
generated
vendored
9
vendor/github.com/moby/moby/client/swarm_update.go
generated
vendored
@ -10,7 +10,8 @@ import (
|
||||
|
||||
// SwarmUpdateOptions contains options for updating a swarm.
|
||||
type SwarmUpdateOptions struct {
|
||||
Swarm swarm.Spec
|
||||
Version swarm.Version
|
||||
Spec swarm.Spec
|
||||
RotateWorkerToken bool
|
||||
RotateManagerToken bool
|
||||
RotateManagerUnlockKey bool
|
||||
@ -20,13 +21,13 @@ type SwarmUpdateOptions struct {
|
||||
type SwarmUpdateResult struct{}
|
||||
|
||||
// SwarmUpdate updates the swarm.
|
||||
func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, options SwarmUpdateOptions) (SwarmUpdateResult, error) {
|
||||
func (cli *Client) SwarmUpdate(ctx context.Context, options SwarmUpdateOptions) (SwarmUpdateResult, error) {
|
||||
query := url.Values{}
|
||||
query.Set("version", version.String())
|
||||
query.Set("version", options.Version.String())
|
||||
query.Set("rotateWorkerToken", strconv.FormatBool(options.RotateWorkerToken))
|
||||
query.Set("rotateManagerToken", strconv.FormatBool(options.RotateManagerToken))
|
||||
query.Set("rotateManagerUnlockKey", strconv.FormatBool(options.RotateManagerUnlockKey))
|
||||
resp, err := cli.post(ctx, "/swarm/update", query, options.Swarm, nil)
|
||||
resp, err := cli.post(ctx, "/swarm/update", query, options.Spec, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
return SwarmUpdateResult{}, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/moby/moby/client/task_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/task_inspect.go
generated
vendored
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/moby/moby/api/types/swarm"
|
||||
)
|
||||
@ -14,7 +15,7 @@ type TaskInspectOptions struct {
|
||||
// TaskInspectResult contains the result of a task inspection.
|
||||
type TaskInspectResult struct {
|
||||
Task swarm.Task
|
||||
Raw []byte
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// TaskInspect returns the task information and its raw representation.
|
||||
@ -25,7 +26,6 @@ func (cli *Client) TaskInspect(ctx context.Context, taskID string, options TaskI
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return TaskInspectResult{}, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/moby/moby/client/utils.go
generated
vendored
4
vendor/github.com/moby/moby/client/utils.go
generated
vendored
@ -70,11 +70,11 @@ func encodePlatform(platform *ocispec.Platform) (string, error) {
|
||||
return string(p), nil
|
||||
}
|
||||
|
||||
func decodeWithRaw[T any](resp *http.Response, out *T) (raw []byte, _ error) {
|
||||
func decodeWithRaw[T any](resp *http.Response, out *T) (raw json.RawMessage, _ error) {
|
||||
if resp == nil || resp.Body == nil {
|
||||
return nil, errors.New("empty response")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
var buf bytes.Buffer
|
||||
tr := io.TeeReader(resp.Body, &buf)
|
||||
|
||||
4
vendor/github.com/moby/moby/client/volume_inspect.go
generated
vendored
4
vendor/github.com/moby/moby/client/volume_inspect.go
generated
vendored
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/moby/moby/api/types/volume"
|
||||
)
|
||||
@ -13,8 +14,8 @@ type VolumeInspectOptions struct {
|
||||
|
||||
// VolumeInspectResult holds the result from the [Client.VolumeInspect] method.
|
||||
type VolumeInspectResult struct {
|
||||
Raw []byte
|
||||
Volume volume.Volume
|
||||
Raw json.RawMessage
|
||||
}
|
||||
|
||||
// VolumeInspect returns the information about a specific volume in the docker host.
|
||||
@ -25,7 +26,6 @@ func (cli *Client) VolumeInspect(ctx context.Context, volumeID string, options V
|
||||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return VolumeInspectResult{}, err
|
||||
}
|
||||
|
||||
28
vendor/github.com/moby/moby/client/volume_list.go
generated
vendored
28
vendor/github.com/moby/moby/client/volume_list.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"slices"
|
||||
|
||||
"github.com/moby/moby/api/types/volume"
|
||||
)
|
||||
@ -15,7 +16,11 @@ type VolumeListOptions struct {
|
||||
|
||||
// VolumeListResult holds the result from the [Client.VolumeList] method.
|
||||
type VolumeListResult struct {
|
||||
Items volume.ListResponse
|
||||
// List of volumes.
|
||||
Items []volume.Volume
|
||||
|
||||
// Warnings that occurred when fetching the list of volumes.
|
||||
Warnings []string
|
||||
}
|
||||
|
||||
// VolumeList returns the volumes configured in the docker host.
|
||||
@ -29,7 +34,22 @@ func (cli *Client) VolumeList(ctx context.Context, options VolumeListOptions) (V
|
||||
return VolumeListResult{}, err
|
||||
}
|
||||
|
||||
var res VolumeListResult
|
||||
err = json.NewDecoder(resp.Body).Decode(&res.Items)
|
||||
return res, err
|
||||
var apiResp volume.ListResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&apiResp)
|
||||
if err != nil {
|
||||
return VolumeListResult{}, err
|
||||
}
|
||||
|
||||
res := VolumeListResult{
|
||||
Items: make([]volume.Volume, 0, len(apiResp.Volumes)),
|
||||
Warnings: slices.Clone(apiResp.Warnings),
|
||||
}
|
||||
|
||||
for _, vol := range apiResp.Volumes {
|
||||
if vol != nil {
|
||||
res.Items = append(res.Items, *vol)
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
6
vendor/modules.txt
vendored
6
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.20251023134003-dcd668d5796b
|
||||
# github.com/moby/moby/api v1.52.0-beta.2.0.20251024193508-be8d6e2f2825
|
||||
## explicit; go 1.23.0
|
||||
github.com/moby/moby/api/pkg/authconfig
|
||||
github.com/moby/moby/api/pkg/progress
|
||||
@ -191,9 +191,8 @@ github.com/moby/moby/api/types/registry
|
||||
github.com/moby/moby/api/types/storage
|
||||
github.com/moby/moby/api/types/swarm
|
||||
github.com/moby/moby/api/types/system
|
||||
github.com/moby/moby/api/types/versions
|
||||
github.com/moby/moby/api/types/volume
|
||||
# github.com/moby/moby/client v0.1.0-beta.2.0.20251023134003-dcd668d5796b
|
||||
# github.com/moby/moby/client v0.1.0-beta.2.0.20251024193508-be8d6e2f2825
|
||||
## explicit; go 1.23.0
|
||||
github.com/moby/moby/client
|
||||
github.com/moby/moby/client/internal
|
||||
@ -201,6 +200,7 @@ github.com/moby/moby/client/internal/timestamp
|
||||
github.com/moby/moby/client/pkg/jsonmessage
|
||||
github.com/moby/moby/client/pkg/security
|
||||
github.com/moby/moby/client/pkg/stringid
|
||||
github.com/moby/moby/client/pkg/versions
|
||||
# github.com/moby/patternmatcher v0.6.0
|
||||
## explicit; go 1.19
|
||||
github.com/moby/patternmatcher
|
||||
|
||||
Reference in New Issue
Block a user