- move api/types/container.ExecOptions to the client
- rename api/types/container.ExecOptions to ExecCreateRequest
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -8,22 +8,6 @@ import "github.com/moby/moby/api/types/common" |
| 8 | 8 |
// TODO(thaJeztah): make this a distinct type. |
| 9 | 9 |
type ExecCreateResponse = common.IDResponse |
| 10 | 10 |
|
| 11 |
-// ExecOptions is a small subset of the Config struct that holds the configuration |
|
| 12 |
-// for the exec feature of docker. |
|
| 13 |
-type ExecOptions struct {
|
|
| 14 |
- User string // User that will run the command |
|
| 15 |
- Privileged bool // Is the container in privileged mode |
|
| 16 |
- Tty bool // Attach standard streams to a tty. |
|
| 17 |
- ConsoleSize *[2]uint `json:",omitempty"` // Initial console size [height, width] |
|
| 18 |
- AttachStdin bool // Attach the standard input, makes possible user interaction |
|
| 19 |
- AttachStderr bool // Attach the standard error |
|
| 20 |
- AttachStdout bool // Attach the standard output |
|
| 21 |
- DetachKeys string // Escape keys for detach |
|
| 22 |
- Env []string // Environment variables |
|
| 23 |
- WorkingDir string // Working directory |
|
| 24 |
- Cmd []string // Execution commands and args |
|
| 25 |
-} |
|
| 26 |
- |
|
| 27 | 11 |
// ExecInspect holds information returned by exec inspect. |
| 28 | 12 |
// |
| 29 | 13 |
// It is used by the client to unmarshal a [ExecInspectResponse], |
| 30 | 14 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+package container |
|
| 1 |
+ |
|
| 2 |
+// ExecCreateRequest is a small subset of the Config struct that holds the configuration |
|
| 3 |
+// for the exec feature of docker. |
|
| 4 |
+type ExecCreateRequest struct {
|
|
| 5 |
+ User string // User that will run the command |
|
| 6 |
+ Privileged bool // Is the container in privileged mode |
|
| 7 |
+ Tty bool // Attach standard streams to a tty. |
|
| 8 |
+ ConsoleSize *[2]uint `json:",omitempty"` // Initial console size [height, width] |
|
| 9 |
+ AttachStdin bool // Attach the standard input, makes possible user interaction |
|
| 10 |
+ AttachStderr bool // Attach the standard error |
|
| 11 |
+ AttachStdout bool // Attach the standard output |
|
| 12 |
+ DetachKeys string // Escape keys for detach |
|
| 13 |
+ Env []string // Environment variables |
|
| 14 |
+ WorkingDir string // Working directory |
|
| 15 |
+ Cmd []string // Execution commands and args |
|
| 16 |
+} |
| ... | ... |
@@ -70,7 +70,7 @@ type ContainerAPIClient interface {
|
| 70 | 70 |
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) |
| 71 | 71 |
ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error) |
| 72 | 72 |
ContainerExecAttach(ctx context.Context, execID string, options ExecAttachOptions) (HijackedResponse, error) |
| 73 |
- ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (container.ExecCreateResponse, error) |
|
| 73 |
+ ContainerExecCreate(ctx context.Context, container string, options ExecCreateOptions) (container.ExecCreateResponse, error) |
|
| 74 | 74 |
ContainerExecInspect(ctx context.Context, execID string) (container.ExecInspect, error) |
| 75 | 75 |
ContainerExecResize(ctx context.Context, execID string, options ContainerResizeOptions) error |
| 76 | 76 |
ContainerExecStart(ctx context.Context, execID string, options ExecStartOptions) error |
| ... | ... |
@@ -9,8 +9,24 @@ import ( |
| 9 | 9 |
"github.com/moby/moby/api/types/versions" |
| 10 | 10 |
) |
| 11 | 11 |
|
| 12 |
+// ExecCreateOptions is a small subset of the Config struct that holds the configuration |
|
| 13 |
+// for the exec feature of docker. |
|
| 14 |
+type ExecCreateOptions struct {
|
|
| 15 |
+ User string // User that will run the command |
|
| 16 |
+ Privileged bool // Is the container in privileged mode |
|
| 17 |
+ Tty bool // Attach standard streams to a tty. |
|
| 18 |
+ ConsoleSize *[2]uint `json:",omitempty"` // Initial console size [height, width] |
|
| 19 |
+ AttachStdin bool // Attach the standard input, makes possible user interaction |
|
| 20 |
+ AttachStderr bool // Attach the standard error |
|
| 21 |
+ AttachStdout bool // Attach the standard output |
|
| 22 |
+ DetachKeys string // Escape keys for detach |
|
| 23 |
+ Env []string // Environment variables |
|
| 24 |
+ WorkingDir string // Working directory |
|
| 25 |
+ Cmd []string // Execution commands and args |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 12 | 28 |
// ContainerExecCreate creates a new exec configuration to run an exec process. |
| 13 |
-func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, options container.ExecOptions) (container.ExecCreateResponse, error) {
|
|
| 29 |
+func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, options ExecCreateOptions) (container.ExecCreateResponse, error) {
|
|
| 14 | 30 |
containerID, err := trimID("container", containerID)
|
| 15 | 31 |
if err != nil {
|
| 16 | 32 |
return container.ExecCreateResponse{}, err
|
| ... | ... |
@@ -32,7 +48,21 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, |
| 32 | 32 |
options.ConsoleSize = nil |
| 33 | 33 |
} |
| 34 | 34 |
|
| 35 |
- resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, options, nil) |
|
| 35 |
+ req := container.ExecCreateRequest{
|
|
| 36 |
+ User: options.User, |
|
| 37 |
+ Privileged: options.Privileged, |
|
| 38 |
+ Tty: options.Tty, |
|
| 39 |
+ ConsoleSize: options.ConsoleSize, |
|
| 40 |
+ AttachStdin: options.AttachStdin, |
|
| 41 |
+ AttachStderr: options.AttachStderr, |
|
| 42 |
+ AttachStdout: options.AttachStdout, |
|
| 43 |
+ DetachKeys: options.DetachKeys, |
|
| 44 |
+ Env: options.Env, |
|
| 45 |
+ WorkingDir: options.WorkingDir, |
|
| 46 |
+ Cmd: options.Cmd, |
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, req, nil) |
|
| 36 | 50 |
defer ensureReaderClosed(resp) |
| 37 | 51 |
if err != nil {
|
| 38 | 52 |
return container.ExecCreateResponse{}, err
|
| ... | ... |
@@ -22,14 +22,14 @@ func TestContainerExecCreateError(t *testing.T) {
|
| 22 | 22 |
) |
| 23 | 23 |
assert.NilError(t, err) |
| 24 | 24 |
|
| 25 |
- _, err = client.ContainerExecCreate(context.Background(), "container_id", container.ExecOptions{})
|
|
| 25 |
+ _, err = client.ContainerExecCreate(context.Background(), "container_id", ExecCreateOptions{})
|
|
| 26 | 26 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal)) |
| 27 | 27 |
|
| 28 |
- _, err = client.ContainerExecCreate(context.Background(), "", container.ExecOptions{})
|
|
| 28 |
+ _, err = client.ContainerExecCreate(context.Background(), "", ExecCreateOptions{})
|
|
| 29 | 29 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 30 | 30 |
assert.Check(t, is.ErrorContains(err, "value is empty")) |
| 31 | 31 |
|
| 32 |
- _, err = client.ContainerExecCreate(context.Background(), " ", container.ExecOptions{})
|
|
| 32 |
+ _, err = client.ContainerExecCreate(context.Background(), " ", ExecCreateOptions{})
|
|
| 33 | 33 |
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) |
| 34 | 34 |
assert.Check(t, is.ErrorContains(err, "value is empty")) |
| 35 | 35 |
} |
| ... | ... |
@@ -42,7 +42,7 @@ func TestContainerExecCreateConnectionError(t *testing.T) {
|
| 42 | 42 |
client, err := NewClientWithOpts(WithAPIVersionNegotiation(), WithHost("tcp://no-such-host.invalid"))
|
| 43 | 43 |
assert.NilError(t, err) |
| 44 | 44 |
|
| 45 |
- _, err = client.ContainerExecCreate(context.Background(), "container_id", container.ExecOptions{})
|
|
| 45 |
+ _, err = client.ContainerExecCreate(context.Background(), "container_id", ExecCreateOptions{})
|
|
| 46 | 46 |
assert.Check(t, is.ErrorType(err, IsErrConnectionFailed)) |
| 47 | 47 |
} |
| 48 | 48 |
|
| ... | ... |
@@ -60,7 +60,7 @@ func TestContainerExecCreate(t *testing.T) {
|
| 60 | 60 |
if err := req.ParseForm(); err != nil {
|
| 61 | 61 |
return nil, err |
| 62 | 62 |
} |
| 63 |
- execConfig := &container.ExecOptions{}
|
|
| 63 |
+ execConfig := &container.ExecCreateRequest{}
|
|
| 64 | 64 |
if err := json.NewDecoder(req.Body).Decode(execConfig); err != nil {
|
| 65 | 65 |
return nil, err |
| 66 | 66 |
} |
| ... | ... |
@@ -81,7 +81,7 @@ func TestContainerExecCreate(t *testing.T) {
|
| 81 | 81 |
) |
| 82 | 82 |
assert.NilError(t, err) |
| 83 | 83 |
|
| 84 |
- r, err := client.ContainerExecCreate(context.Background(), "container_id", container.ExecOptions{
|
|
| 84 |
+ r, err := client.ContainerExecCreate(context.Background(), "container_id", ExecCreateOptions{
|
|
| 85 | 85 |
User: "user", |
| 86 | 86 |
}) |
| 87 | 87 |
assert.NilError(t, err) |
| ... | ... |
@@ -93,7 +93,7 @@ func (daemon *Daemon) getActiveContainer(name string) (*container.Container, err |
| 93 | 93 |
} |
| 94 | 94 |
|
| 95 | 95 |
// ContainerExecCreate sets up an exec in a running container. |
| 96 |
-func (daemon *Daemon) ContainerExecCreate(name string, options *containertypes.ExecOptions) (string, error) {
|
|
| 96 |
+func (daemon *Daemon) ContainerExecCreate(name string, options *containertypes.ExecCreateRequest) (string, error) {
|
|
| 97 | 97 |
cntr, err := daemon.getActiveContainer(name) |
| 98 | 98 |
if err != nil {
|
| 99 | 99 |
return "", err |
| ... | ... |
@@ -14,7 +14,7 @@ import ( |
| 14 | 14 |
|
| 15 | 15 |
// execBackend includes functions to implement to provide exec functionality. |
| 16 | 16 |
type execBackend interface {
|
| 17 |
- ContainerExecCreate(name string, options *container.ExecOptions) (string, error) |
|
| 17 |
+ ContainerExecCreate(name string, options *container.ExecCreateRequest) (string, error) |
|
| 18 | 18 |
ContainerExecInspect(id string) (*backend.ExecInspect, error) |
| 19 | 19 |
ContainerExecResize(ctx context.Context, name string, height, width uint32) error |
| 20 | 20 |
ContainerExecStart(ctx context.Context, name string, options backend.ExecStartConfig) error |
| ... | ... |
@@ -39,7 +39,7 @@ func (c *containerRouter) postContainerExecCreate(ctx context.Context, w http.Re |
| 39 | 39 |
return err |
| 40 | 40 |
} |
| 41 | 41 |
|
| 42 |
- execConfig := &container.ExecOptions{}
|
|
| 42 |
+ execConfig := &container.ExecCreateRequest{}
|
|
| 43 | 43 |
if err := httputils.ReadJSON(r, execConfig); err != nil {
|
| 44 | 44 |
return err |
| 45 | 45 |
} |
| ... | ... |
@@ -12,7 +12,6 @@ import ( |
| 12 | 12 |
"testing" |
| 13 | 13 |
"time" |
| 14 | 14 |
|
| 15 |
- "github.com/moby/moby/api/types/container" |
|
| 16 | 15 |
"github.com/moby/moby/client" |
| 17 | 16 |
"github.com/moby/moby/v2/integration-cli/checker" |
| 18 | 17 |
"github.com/moby/moby/v2/integration-cli/cli" |
| ... | ... |
@@ -65,7 +64,7 @@ func (s *DockerAPISuite) TestExecAPICreateContainerPaused(c *testing.T) {
|
| 65 | 65 |
assert.NilError(c, err) |
| 66 | 66 |
defer apiClient.Close() |
| 67 | 67 |
|
| 68 |
- _, err = apiClient.ContainerExecCreate(testutil.GetContext(c), name, container.ExecOptions{
|
|
| 68 |
+ _, err = apiClient.ContainerExecCreate(testutil.GetContext(c), name, client.ExecCreateOptions{
|
|
| 69 | 69 |
Cmd: []string{"true"},
|
| 70 | 70 |
}) |
| 71 | 71 |
assert.ErrorContains(c, err, "Container "+name+" is paused, unpause the container before exec", "Expected message when creating exec command with Container %s is paused", name) |
| ... | ... |
@@ -129,7 +128,7 @@ func (s *DockerAPISuite) TestExecAPIStartWithDetach(c *testing.T) {
|
| 129 | 129 |
assert.NilError(c, err) |
| 130 | 130 |
defer apiClient.Close() |
| 131 | 131 |
|
| 132 |
- createResp, err := apiClient.ContainerExecCreate(ctx, name, container.ExecOptions{
|
|
| 132 |
+ createResp, err := apiClient.ContainerExecCreate(ctx, name, client.ExecCreateOptions{
|
|
| 133 | 133 |
Cmd: []string{"true"},
|
| 134 | 134 |
AttachStderr: true, |
| 135 | 135 |
}) |
| ... | ... |
@@ -10,7 +10,6 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
cerrdefs "github.com/containerd/errdefs" |
| 12 | 12 |
"github.com/moby/moby/api/pkg/stdcopy" |
| 13 |
- "github.com/moby/moby/api/types/container" |
|
| 14 | 13 |
"github.com/moby/moby/api/types/filters" |
| 15 | 14 |
swarmtypes "github.com/moby/moby/api/types/swarm" |
| 16 | 15 |
"github.com/moby/moby/client" |
| ... | ... |
@@ -312,7 +311,7 @@ func TestTemplatedConfig(t *testing.T) {
|
| 312 | 312 |
tasks := swarm.GetRunningTasks(ctx, t, c, serviceID) |
| 313 | 313 |
assert.Assert(t, len(tasks) > 0, "no running tasks found for service %s", serviceID) |
| 314 | 314 |
|
| 315 |
- resp := swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{
|
|
| 315 |
+ resp := swarm.ExecTask(ctx, t, d, tasks[0], client.ExecCreateOptions{
|
|
| 316 | 316 |
Cmd: []string{"/bin/cat", "/templated_config"},
|
| 317 | 317 |
AttachStdout: true, |
| 318 | 318 |
AttachStderr: true, |
| ... | ... |
@@ -327,7 +326,7 @@ func TestTemplatedConfig(t *testing.T) {
|
| 327 | 327 |
|
| 328 | 328 |
outBuf.Reset() |
| 329 | 329 |
errBuf.Reset() |
| 330 |
- resp = swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{
|
|
| 330 |
+ resp = swarm.ExecTask(ctx, t, d, tasks[0], client.ExecCreateOptions{
|
|
| 331 | 331 |
Cmd: []string{"mount"},
|
| 332 | 332 |
AttachStdout: true, |
| 333 | 333 |
AttachStderr: true, |
| ... | ... |
@@ -4,8 +4,8 @@ import ( |
| 4 | 4 |
"strings" |
| 5 | 5 |
"testing" |
| 6 | 6 |
|
| 7 |
- containertypes "github.com/moby/moby/api/types/container" |
|
| 8 | 7 |
"github.com/moby/moby/api/types/versions" |
| 8 |
+ "github.com/moby/moby/client" |
|
| 9 | 9 |
"github.com/moby/moby/v2/integration/internal/container" |
| 10 | 10 |
"gotest.tools/v3/assert" |
| 11 | 11 |
"gotest.tools/v3/skip" |
| ... | ... |
@@ -21,7 +21,7 @@ func TestExecConsoleSize(t *testing.T) {
|
| 21 | 21 |
cID := container.Run(ctx, t, apiClient, container.WithImage("busybox"))
|
| 22 | 22 |
|
| 23 | 23 |
result, err := container.Exec(ctx, apiClient, cID, []string{"stty", "size"},
|
| 24 |
- func(ec *containertypes.ExecOptions) {
|
|
| 24 |
+ func(ec *client.ExecCreateOptions) {
|
|
| 25 | 25 |
ec.Tty = true |
| 26 | 26 |
ec.ConsoleSize = &[2]uint{57, 123}
|
| 27 | 27 |
}, |
| ... | ... |
@@ -12,7 +12,6 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
cerrdefs "github.com/containerd/errdefs" |
| 14 | 14 |
"github.com/moby/moby/api/types/common" |
| 15 |
- containertypes "github.com/moby/moby/api/types/container" |
|
| 16 | 15 |
"github.com/moby/moby/client" |
| 17 | 16 |
"github.com/moby/moby/v2/integration/internal/build" |
| 18 | 17 |
"github.com/moby/moby/v2/integration/internal/container" |
| ... | ... |
@@ -34,7 +33,7 @@ func TestExecWithCloseStdin(t *testing.T) {
|
| 34 | 34 |
cID := container.Run(ctx, t, apiClient) |
| 35 | 35 |
|
| 36 | 36 |
const expected = "closeIO" |
| 37 |
- execResp, err := apiClient.ContainerExecCreate(ctx, cID, containertypes.ExecOptions{
|
|
| 37 |
+ execResp, err := apiClient.ContainerExecCreate(ctx, cID, client.ExecCreateOptions{
|
|
| 38 | 38 |
AttachStdin: true, |
| 39 | 39 |
AttachStdout: true, |
| 40 | 40 |
Cmd: []string{"sh", "-c", "cat && echo " + expected},
|
| ... | ... |
@@ -89,7 +88,7 @@ func TestExec(t *testing.T) {
|
| 89 | 89 |
|
| 90 | 90 |
cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithWorkingDir("/root"))
|
| 91 | 91 |
|
| 92 |
- id, err := apiClient.ContainerExecCreate(ctx, cID, containertypes.ExecOptions{
|
|
| 92 |
+ id, err := apiClient.ContainerExecCreate(ctx, cID, client.ExecCreateOptions{
|
|
| 93 | 93 |
WorkingDir: "/tmp", |
| 94 | 94 |
Env: []string{"FOO=BAR"},
|
| 95 | 95 |
AttachStdout: true, |
| ... | ... |
@@ -127,7 +126,7 @@ func TestExecResize(t *testing.T) {
|
| 127 | 127 |
if runtime.GOOS == "windows" {
|
| 128 | 128 |
cmd = []string{"sleep", "240"}
|
| 129 | 129 |
} |
| 130 |
- resp, err := apiClient.ContainerExecCreate(ctx, cID, containertypes.ExecOptions{
|
|
| 130 |
+ resp, err := apiClient.ContainerExecCreate(ctx, cID, client.ExecCreateOptions{
|
|
| 131 | 131 |
Tty: true, // Windows requires a TTY for the resize to work, otherwise fails with "is not a tty: failed precondition", see https://github.com/moby/moby/pull/48665#issuecomment-2412530345 |
| 132 | 132 |
Cmd: cmd, |
| 133 | 133 |
}) |
| ... | ... |
@@ -296,8 +295,8 @@ func TestExecUser(t *testing.T) {
|
| 296 | 296 |
withoutEtcGroups := container.WithImage(build.Do(ctx, t, apiClient, fakecontext.New(t, "", fakecontext.WithDockerfile("FROM busybox\nRUN rm /etc/group"))))
|
| 297 | 297 |
withoutEtcPasswd := container.WithImage(build.Do(ctx, t, apiClient, fakecontext.New(t, "", fakecontext.WithDockerfile("FROM busybox\nRUN rm /etc/passwd"))))
|
| 298 | 298 |
|
| 299 |
- withUser := func(user string) func(options *containertypes.ExecOptions) {
|
|
| 300 |
- return func(options *containertypes.ExecOptions) { options.User = user }
|
|
| 299 |
+ withUser := func(user string) func(options *client.ExecCreateOptions) {
|
|
| 300 |
+ return func(options *client.ExecCreateOptions) { options.User = user }
|
|
| 301 | 301 |
} |
| 302 | 302 |
|
| 303 | 303 |
tests := []struct {
|
| ... | ... |
@@ -5,7 +5,6 @@ import ( |
| 5 | 5 |
"context" |
| 6 | 6 |
"testing" |
| 7 | 7 |
|
| 8 |
- "github.com/moby/moby/api/types/container" |
|
| 9 | 8 |
"github.com/moby/moby/client" |
| 10 | 9 |
) |
| 11 | 10 |
|
| ... | ... |
@@ -47,9 +46,9 @@ func (res ExecResult) AssertSuccess(t testing.TB) {
|
| 47 | 47 |
// containing stdout, stderr, and exit code. Note: |
| 48 | 48 |
// - this is a synchronous operation; |
| 49 | 49 |
// - cmd stdin is closed. |
| 50 |
-func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []string, ops ...func(*container.ExecOptions)) (ExecResult, error) {
|
|
| 50 |
+func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []string, ops ...func(*client.ExecCreateOptions)) (ExecResult, error) {
|
|
| 51 | 51 |
// prepare exec |
| 52 |
- execOptions := container.ExecOptions{
|
|
| 52 |
+ execOptions := client.ExecCreateOptions{
|
|
| 53 | 53 |
AttachStdout: true, |
| 54 | 54 |
AttachStderr: true, |
| 55 | 55 |
Cmd: cmd, |
| ... | ... |
@@ -87,7 +86,7 @@ func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []stri |
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 | 89 |
// ExecT calls Exec() and aborts the test if an error occurs. |
| 90 |
-func ExecT(ctx context.Context, t testing.TB, apiClient client.APIClient, id string, cmd []string, ops ...func(*container.ExecOptions)) ExecResult {
|
|
| 90 |
+func ExecT(ctx context.Context, t testing.TB, apiClient client.APIClient, id string, cmd []string, ops ...func(*client.ExecCreateOptions)) ExecResult {
|
|
| 91 | 91 |
t.Helper() |
| 92 | 92 |
res, err := Exec(ctx, apiClient, id, cmd, ops...) |
| 93 | 93 |
if err != nil {
|
| ... | ... |
@@ -6,7 +6,6 @@ import ( |
| 6 | 6 |
"testing" |
| 7 | 7 |
"time" |
| 8 | 8 |
|
| 9 |
- "github.com/moby/moby/api/types/container" |
|
| 10 | 9 |
"github.com/moby/moby/api/types/filters" |
| 11 | 10 |
swarmtypes "github.com/moby/moby/api/types/swarm" |
| 12 | 11 |
"github.com/moby/moby/client" |
| ... | ... |
@@ -211,7 +210,7 @@ func GetRunningTasks(ctx context.Context, t *testing.T, c client.ServiceAPIClien |
| 211 | 211 |
} |
| 212 | 212 |
|
| 213 | 213 |
// ExecTask runs the passed in exec config on the given task |
| 214 |
-func ExecTask(ctx context.Context, t *testing.T, d *daemon.Daemon, task swarmtypes.Task, options container.ExecOptions) client.HijackedResponse {
|
|
| 214 |
+func ExecTask(ctx context.Context, t *testing.T, d *daemon.Daemon, task swarmtypes.Task, options client.ExecCreateOptions) client.HijackedResponse {
|
|
| 215 | 215 |
t.Helper() |
| 216 | 216 |
apiClient := d.NewClientT(t) |
| 217 | 217 |
defer apiClient.Close() |
| ... | ... |
@@ -10,7 +10,6 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
cerrdefs "github.com/containerd/errdefs" |
| 12 | 12 |
"github.com/moby/moby/api/pkg/stdcopy" |
| 13 |
- "github.com/moby/moby/api/types/container" |
|
| 14 | 13 |
"github.com/moby/moby/api/types/filters" |
| 15 | 14 |
swarmtypes "github.com/moby/moby/api/types/swarm" |
| 16 | 15 |
"github.com/moby/moby/client" |
| ... | ... |
@@ -313,7 +312,7 @@ func TestTemplatedSecret(t *testing.T) {
|
| 313 | 313 |
tasks := swarm.GetRunningTasks(ctx, t, c, serviceID) |
| 314 | 314 |
assert.Assert(t, len(tasks) > 0, "no running tasks found for service %s", serviceID) |
| 315 | 315 |
|
| 316 |
- resp := swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{
|
|
| 316 |
+ resp := swarm.ExecTask(ctx, t, d, tasks[0], client.ExecCreateOptions{
|
|
| 317 | 317 |
Cmd: []string{"/bin/cat", "/run/secrets/templated_secret"},
|
| 318 | 318 |
AttachStdout: true, |
| 319 | 319 |
AttachStderr: true, |
| ... | ... |
@@ -328,7 +327,7 @@ func TestTemplatedSecret(t *testing.T) {
|
| 328 | 328 |
|
| 329 | 329 |
outBuf.Reset() |
| 330 | 330 |
errBuf.Reset() |
| 331 |
- resp = swarm.ExecTask(ctx, t, d, tasks[0], container.ExecOptions{
|
|
| 331 |
+ resp = swarm.ExecTask(ctx, t, d, tasks[0], client.ExecCreateOptions{
|
|
| 332 | 332 |
Cmd: []string{"mount"},
|
| 333 | 333 |
AttachStdout: true, |
| 334 | 334 |
AttachStderr: true, |
| ... | ... |
@@ -8,7 +8,6 @@ import ( |
| 8 | 8 |
"testing" |
| 9 | 9 |
"time" |
| 10 | 10 |
|
| 11 |
- containertypes "github.com/moby/moby/api/types/container" |
|
| 12 | 11 |
"github.com/moby/moby/api/types/events" |
| 13 | 12 |
"github.com/moby/moby/api/types/filters" |
| 14 | 13 |
"github.com/moby/moby/api/types/mount" |
| ... | ... |
@@ -28,7 +27,7 @@ func TestEventsExecDie(t *testing.T) {
|
| 28 | 28 |
|
| 29 | 29 |
cID := container.Run(ctx, t, apiClient) |
| 30 | 30 |
|
| 31 |
- id, err := apiClient.ContainerExecCreate(ctx, cID, containertypes.ExecOptions{
|
|
| 31 |
+ id, err := apiClient.ContainerExecCreate(ctx, cID, client.ExecCreateOptions{
|
|
| 32 | 32 |
Cmd: []string{"echo", "hello"},
|
| 33 | 33 |
}) |
| 34 | 34 |
assert.NilError(t, err) |
| ... | ... |
@@ -8,22 +8,6 @@ import "github.com/moby/moby/api/types/common" |
| 8 | 8 |
// TODO(thaJeztah): make this a distinct type. |
| 9 | 9 |
type ExecCreateResponse = common.IDResponse |
| 10 | 10 |
|
| 11 |
-// ExecOptions is a small subset of the Config struct that holds the configuration |
|
| 12 |
-// for the exec feature of docker. |
|
| 13 |
-type ExecOptions struct {
|
|
| 14 |
- User string // User that will run the command |
|
| 15 |
- Privileged bool // Is the container in privileged mode |
|
| 16 |
- Tty bool // Attach standard streams to a tty. |
|
| 17 |
- ConsoleSize *[2]uint `json:",omitempty"` // Initial console size [height, width] |
|
| 18 |
- AttachStdin bool // Attach the standard input, makes possible user interaction |
|
| 19 |
- AttachStderr bool // Attach the standard error |
|
| 20 |
- AttachStdout bool // Attach the standard output |
|
| 21 |
- DetachKeys string // Escape keys for detach |
|
| 22 |
- Env []string // Environment variables |
|
| 23 |
- WorkingDir string // Working directory |
|
| 24 |
- Cmd []string // Execution commands and args |
|
| 25 |
-} |
|
| 26 |
- |
|
| 27 | 11 |
// ExecInspect holds information returned by exec inspect. |
| 28 | 12 |
// |
| 29 | 13 |
// It is used by the client to unmarshal a [ExecInspectResponse], |
| 30 | 14 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+package container |
|
| 1 |
+ |
|
| 2 |
+// ExecCreateRequest is a small subset of the Config struct that holds the configuration |
|
| 3 |
+// for the exec feature of docker. |
|
| 4 |
+type ExecCreateRequest struct {
|
|
| 5 |
+ User string // User that will run the command |
|
| 6 |
+ Privileged bool // Is the container in privileged mode |
|
| 7 |
+ Tty bool // Attach standard streams to a tty. |
|
| 8 |
+ ConsoleSize *[2]uint `json:",omitempty"` // Initial console size [height, width] |
|
| 9 |
+ AttachStdin bool // Attach the standard input, makes possible user interaction |
|
| 10 |
+ AttachStderr bool // Attach the standard error |
|
| 11 |
+ AttachStdout bool // Attach the standard output |
|
| 12 |
+ DetachKeys string // Escape keys for detach |
|
| 13 |
+ Env []string // Environment variables |
|
| 14 |
+ WorkingDir string // Working directory |
|
| 15 |
+ Cmd []string // Execution commands and args |
|
| 16 |
+} |
| ... | ... |
@@ -70,7 +70,7 @@ type ContainerAPIClient interface {
|
| 70 | 70 |
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) |
| 71 | 71 |
ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error) |
| 72 | 72 |
ContainerExecAttach(ctx context.Context, execID string, options ExecAttachOptions) (HijackedResponse, error) |
| 73 |
- ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (container.ExecCreateResponse, error) |
|
| 73 |
+ ContainerExecCreate(ctx context.Context, container string, options ExecCreateOptions) (container.ExecCreateResponse, error) |
|
| 74 | 74 |
ContainerExecInspect(ctx context.Context, execID string) (container.ExecInspect, error) |
| 75 | 75 |
ContainerExecResize(ctx context.Context, execID string, options ContainerResizeOptions) error |
| 76 | 76 |
ContainerExecStart(ctx context.Context, execID string, options ExecStartOptions) error |
| ... | ... |
@@ -9,8 +9,24 @@ import ( |
| 9 | 9 |
"github.com/moby/moby/api/types/versions" |
| 10 | 10 |
) |
| 11 | 11 |
|
| 12 |
+// ExecCreateOptions is a small subset of the Config struct that holds the configuration |
|
| 13 |
+// for the exec feature of docker. |
|
| 14 |
+type ExecCreateOptions struct {
|
|
| 15 |
+ User string // User that will run the command |
|
| 16 |
+ Privileged bool // Is the container in privileged mode |
|
| 17 |
+ Tty bool // Attach standard streams to a tty. |
|
| 18 |
+ ConsoleSize *[2]uint `json:",omitempty"` // Initial console size [height, width] |
|
| 19 |
+ AttachStdin bool // Attach the standard input, makes possible user interaction |
|
| 20 |
+ AttachStderr bool // Attach the standard error |
|
| 21 |
+ AttachStdout bool // Attach the standard output |
|
| 22 |
+ DetachKeys string // Escape keys for detach |
|
| 23 |
+ Env []string // Environment variables |
|
| 24 |
+ WorkingDir string // Working directory |
|
| 25 |
+ Cmd []string // Execution commands and args |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 12 | 28 |
// ContainerExecCreate creates a new exec configuration to run an exec process. |
| 13 |
-func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, options container.ExecOptions) (container.ExecCreateResponse, error) {
|
|
| 29 |
+func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, options ExecCreateOptions) (container.ExecCreateResponse, error) {
|
|
| 14 | 30 |
containerID, err := trimID("container", containerID)
|
| 15 | 31 |
if err != nil {
|
| 16 | 32 |
return container.ExecCreateResponse{}, err
|
| ... | ... |
@@ -32,7 +48,21 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, |
| 32 | 32 |
options.ConsoleSize = nil |
| 33 | 33 |
} |
| 34 | 34 |
|
| 35 |
- resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, options, nil) |
|
| 35 |
+ req := container.ExecCreateRequest{
|
|
| 36 |
+ User: options.User, |
|
| 37 |
+ Privileged: options.Privileged, |
|
| 38 |
+ Tty: options.Tty, |
|
| 39 |
+ ConsoleSize: options.ConsoleSize, |
|
| 40 |
+ AttachStdin: options.AttachStdin, |
|
| 41 |
+ AttachStderr: options.AttachStderr, |
|
| 42 |
+ AttachStdout: options.AttachStdout, |
|
| 43 |
+ DetachKeys: options.DetachKeys, |
|
| 44 |
+ Env: options.Env, |
|
| 45 |
+ WorkingDir: options.WorkingDir, |
|
| 46 |
+ Cmd: options.Cmd, |
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, req, nil) |
|
| 36 | 50 |
defer ensureReaderClosed(resp) |
| 37 | 51 |
if err != nil {
|
| 38 | 52 |
return container.ExecCreateResponse{}, err
|