Skip to content

Commit e3af012

Browse files
author
zhangyue
committed
bugfix: start cli setRawMode when in tty mode and Terminal
Signed-off-by: zhangyue <[email protected]>
1 parent b2542f1 commit e3af012

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

cli/start.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ func (s *StartCommand) addFlags() {
6060
func (s *StartCommand) runStart(args []string) error {
6161
ctx := context.Background()
6262
apiClient := s.cli.Client()
63-
6463
// attach to io.
6564
if s.attach || s.stdin {
6665
var wait chan struct{}
@@ -69,17 +68,28 @@ func (s *StartCommand) runStart(args []string) error {
6968
return fmt.Errorf("cannot start and attach multiple containers at once")
7069
}
7170

72-
in, out, err := setRawMode(s.stdin, false)
71+
container := args[0]
72+
c, err := apiClient.ContainerGet(ctx, container)
7373
if err != nil {
74-
return fmt.Errorf("failed to set raw mode")
74+
return err
7575
}
76-
defer func() {
77-
if err := restoreMode(in, out); err != nil {
78-
fmt.Fprintf(os.Stderr, "failed to restore term mode")
76+
77+
if err := checkTty(s.attach, c.Config.Tty, os.Stdout.Fd()); err != nil {
78+
return err
79+
}
80+
81+
if c.Config.Tty {
82+
in, out, err := setRawMode(s.stdin, false)
83+
if err != nil {
84+
return fmt.Errorf("failed to set raw mode")
7985
}
80-
}()
86+
defer func() {
87+
if err := restoreMode(in, out); err != nil {
88+
fmt.Fprintf(os.Stderr, "failed to restore term mode")
89+
}
90+
}()
91+
}
8192

82-
container := args[0]
8393
conn, br, err := apiClient.ContainerAttach(ctx, container, s.stdin)
8494
if err != nil {
8595
return fmt.Errorf("failed to attach container: %v", err)
@@ -175,6 +185,15 @@ func restoreMode(in, out *terminal.State) error {
175185
return nil
176186
}
177187

188+
// CheckTty checks if we are trying to attach to a container tty
189+
// from a non-tty client input stream, and if so, returns an error.
190+
func checkTty(attachStdin, ttyMode bool, fd uintptr) error {
191+
if ttyMode && attachStdin && !terminal.IsTerminal(int(fd)) {
192+
return errors.New("the input device is not a TTY")
193+
}
194+
return nil
195+
}
196+
178197
// startExample shows examples in start command, and is used in auto-generated cli docs.
179198
func startExample() string {
180199
return `$ pouch ps -a

test/cli_start_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/go-check/check"
1616
"github.com/gotestyourself/gotestyourself/icmd"
1717
"github.com/kr/pty"
18+
"github.com/stretchr/testify/assert"
1819
)
1920

2021
// PouchStartSuite is the test suite for start CLI.
@@ -324,6 +325,18 @@ func (suite *PouchStartSuite) TestStartFromCheckpoint(c *check.C) {
324325
command.PouchRun("start", "--checkpoint-dir", tmpDir, "--checkpoint", checkpoint, restoredContainer).Assert(c, icmd.Success)
325326
}
326327

328+
// TestStartWithTty tests running container with -tty flag and attach stdin in a non-tty client.
329+
func (suite *PouchStartSuite) TestStartWithTty(c *check.C) {
330+
name := "TestStartWithTty"
331+
res := command.PouchRun("create", "-t", "--name", name, busyboxImage, "/bin/sh", "-c", "while true;do echo hello;done")
332+
defer DelContainerForceMultyTime(c, name)
333+
res.Assert(c, icmd.Success)
334+
335+
attachRes := command.PouchRun("start", "-a", "-i", name)
336+
errString := attachRes.Stderr()
337+
assert.Equal(c, errString, "Error: the input device is not a TTY\n")
338+
}
339+
327340
// TestStartMultiContainers tries to start more than one container.
328341
func (suite *PouchStartSuite) TestStartMultiContainers(c *check.C) {
329342
containernames := []string{"TestStartMultiContainer-1", "TestStartMultiContainer-2"}

0 commit comments

Comments
 (0)