Skip to content

Commit 1d4b4e3

Browse files
committed
use docker/cli RunExec and RunStart to handle all the interactive/tty/* terminal logic
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent d999c23 commit 1d4b4e3

File tree

8 files changed

+48
-309
lines changed

8 files changed

+48
-309
lines changed

cmd/compose/run.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ func (opts runOptions) apply(project *types.Project) error {
6262
if err != nil {
6363
return err
6464
}
65+
66+
target.Tty = !opts.noTty
67+
target.StdinOpen = opts.interactive
6568
if !opts.servicePorts {
6669
target.Ports = []types.ServicePortConfig{}
6770
}
@@ -207,6 +210,7 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
207210
Detach: opts.Detach,
208211
AutoRemove: opts.Remove,
209212
Tty: !opts.noTty,
213+
Interactive: opts.interactive,
210214
WorkingDir: opts.workdir,
211215
User: opts.user,
212216
Environment: opts.environment,

cmd/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func pluginMain() {
6868
}
6969

7070
func main() {
71-
if commands.RunningAsStandalone() {
71+
if plugin.RunningStandalone() {
7272
os.Args = append([]string{"docker"}, compatibility.Convert(os.Args[1:])...)
7373
}
7474
pluginMain()

pkg/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ type RunOptions struct {
216216
Detach bool
217217
AutoRemove bool
218218
Tty bool
219+
Interactive bool
219220
WorkingDir string
220221
User string
221222
Environment []string

pkg/compose/exec.go

Lines changed: 19 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -19,123 +19,41 @@ package compose
1919
import (
2020
"context"
2121
"fmt"
22-
"io"
2322

23+
"github.com/docker/cli/cli"
24+
"github.com/docker/cli/cli/command/container"
25+
"github.com/docker/compose/v2/pkg/api"
2426
moby "github.com/docker/docker/api/types"
2527
"github.com/docker/docker/api/types/filters"
26-
"github.com/docker/docker/pkg/stdcopy"
27-
"github.com/moby/term"
28-
29-
"github.com/docker/compose/v2/pkg/api"
3028
)
3129

3230
func (s *composeService) Exec(ctx context.Context, project string, opts api.RunOptions) (int, error) {
33-
container, err := s.getExecTarget(ctx, project, opts)
34-
if err != nil {
35-
return 0, err
36-
}
37-
38-
exec, err := s.apiClient().ContainerExecCreate(ctx, container.ID, moby.ExecConfig{
39-
Cmd: opts.Command,
40-
Env: opts.Environment,
41-
User: opts.User,
42-
Privileged: opts.Privileged,
43-
Tty: opts.Tty,
44-
Detach: opts.Detach,
45-
WorkingDir: opts.WorkingDir,
46-
47-
AttachStdin: true,
48-
AttachStdout: true,
49-
AttachStderr: true,
50-
})
51-
if err != nil {
52-
return 0, err
53-
}
54-
55-
if opts.Detach {
56-
return 0, s.apiClient().ContainerExecStart(ctx, exec.ID, moby.ExecStartCheck{
57-
Detach: true,
58-
Tty: opts.Tty,
59-
})
60-
}
61-
62-
resp, err := s.apiClient().ContainerExecAttach(ctx, exec.ID, moby.ExecStartCheck{
63-
Tty: opts.Tty,
64-
})
31+
target, err := s.getExecTarget(ctx, project, opts)
6532
if err != nil {
6633
return 0, err
6734
}
68-
defer resp.Close() //nolint:errcheck
6935

70-
if opts.Tty {
71-
s.monitorTTySize(ctx, exec.ID, s.apiClient().ContainerExecResize)
36+
exec := container.NewExecOptions()
37+
exec.Interactive = opts.Interactive
38+
exec.TTY = opts.Tty
39+
exec.Detach = opts.Detach
40+
exec.User = opts.User
41+
exec.Privileged = opts.Privileged
42+
exec.Workdir = opts.WorkingDir
43+
exec.Container = target.ID
44+
exec.Command = opts.Command
45+
for _, v := range opts.Environment {
46+
err := exec.Env.Set(v)
7247
if err != nil {
7348
return 0, err
7449
}
7550
}
7651

77-
err = s.interactiveExec(ctx, opts, resp)
78-
if err != nil {
79-
return 0, err
80-
}
81-
82-
return s.getExecExitStatus(ctx, exec.ID)
83-
}
84-
85-
// inspired by https://github.com/docker/cli/blob/master/cli/command/container/exec.go#L116
86-
func (s *composeService) interactiveExec(ctx context.Context, opts api.RunOptions, resp moby.HijackedResponse) error {
87-
outputDone := make(chan error)
88-
inputDone := make(chan error)
89-
90-
stdout := ContainerStdout{HijackedResponse: resp}
91-
stdin := ContainerStdin{HijackedResponse: resp}
92-
r, err := s.getEscapeKeyProxy(s.stdin(), opts.Tty)
93-
if err != nil {
94-
return err
95-
}
96-
97-
in := s.stdin()
98-
if in.IsTerminal() && opts.Tty {
99-
state, err := term.SetRawTerminal(in.FD())
100-
if err != nil {
101-
return err
102-
}
103-
defer term.RestoreTerminal(in.FD(), state) //nolint:errcheck
104-
}
105-
106-
go func() {
107-
if opts.Tty {
108-
_, err := io.Copy(s.stdout(), stdout)
109-
outputDone <- err
110-
} else {
111-
_, err := stdcopy.StdCopy(s.stdout(), s.stderr(), stdout)
112-
outputDone <- err
113-
}
114-
stdout.Close() //nolint:errcheck
115-
}()
116-
117-
go func() {
118-
_, err := io.Copy(stdin, r)
119-
inputDone <- err
120-
stdin.Close() //nolint:errcheck
121-
}()
122-
123-
for {
124-
select {
125-
case err := <-outputDone:
126-
return err
127-
case err := <-inputDone:
128-
if _, ok := err.(term.EscapeError); ok {
129-
return nil
130-
}
131-
if err != nil {
132-
return err
133-
}
134-
// Wait for output to complete streaming
135-
case <-ctx.Done():
136-
return ctx.Err()
137-
}
52+
err = container.RunExec(s.dockerCli, exec)
53+
if sterr, ok := err.(cli.StatusError); ok {
54+
return sterr.StatusCode, nil
13855
}
56+
return 0, err
13957
}
14058

14159
func (s *composeService) getExecTarget(ctx context.Context, projectName string, opts api.RunOptions) (moby.Container, error) {
@@ -155,11 +73,3 @@ func (s *composeService) getExecTarget(ctx context.Context, projectName string,
15573
container := containers[0]
15674
return container, nil
15775
}
158-
159-
func (s *composeService) getExecExitStatus(ctx context.Context, execID string) (int, error) {
160-
resp, err := s.apiClient().ContainerExecInspect(ctx, execID)
161-
if err != nil {
162-
return 0, err
163-
}
164-
return resp.ExitCode, nil
165-
}

pkg/compose/resize.go

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)