-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathtty.go
More file actions
103 lines (93 loc) · 2.56 KB
/
tty.go
File metadata and controls
103 lines (93 loc) · 2.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package container
import (
"context"
"fmt"
"os"
gosignal "os/signal"
"runtime"
"time"
"github.com/docker/cli/cli/command"
"github.com/moby/moby/client"
"github.com/moby/sys/signal"
"github.com/sirupsen/logrus"
)
// TODO(thaJeztah): split resizeTTYTo
type resizeClient interface {
client.ExecAPIClient
client.ContainerAPIClient
}
// resizeTTYTo resizes TTY to specific height and width.
func resizeTTYTo(ctx context.Context, apiClient resizeClient, id string, height, width uint, isExec bool) error {
if height == 0 && width == 0 {
return nil
}
var err error
if isExec {
_, err = apiClient.ExecResize(ctx, id, client.ExecResizeOptions{
Height: height,
Width: width,
})
} else {
_, err = apiClient.ContainerResize(ctx, id, client.ContainerResizeOptions{
Height: height,
Width: width,
})
}
if err != nil {
logrus.Debugf("Error resize: %s\r", err)
}
return err
}
// resizeTty is to resize the tty with cli out's tty size
func resizeTty(ctx context.Context, cli command.Cli, id string, isExec bool) error {
height, width := cli.Out().GetTtySize()
return resizeTTYTo(ctx, cli.Client(), id, height, width, isExec)
}
// initTtySize is to init the TTYs size to the same as the window, if there is an error, it will retry 10 times.
func initTtySize(ctx context.Context, cli command.Cli, id string, isExec bool, resizeTtyFunc func(ctx context.Context, cli command.Cli, id string, isExec bool) error) {
rTTYfunc := resizeTtyFunc
if rTTYfunc == nil {
rTTYfunc = resizeTty
}
if err := rTTYfunc(ctx, cli, id, isExec); err != nil {
go func() {
var err error
for retry := 0; retry < 10; retry++ {
time.Sleep(time.Duration(retry+1) * 10 * time.Millisecond)
if err = rTTYfunc(ctx, cli, id, isExec); err == nil {
break
}
}
if err != nil {
_, _ = fmt.Fprintln(cli.Err(), "failed to resize tty, using default size")
}
}()
}
}
// MonitorTtySize updates the container tty size when the terminal tty changes size
func MonitorTtySize(ctx context.Context, cli command.Cli, id string, isExec bool) error {
initTtySize(ctx, cli, id, isExec, resizeTty)
if runtime.GOOS == "windows" {
go func() {
prevH, prevW := cli.Out().GetTtySize()
for {
time.Sleep(time.Millisecond * 250)
h, w := cli.Out().GetTtySize()
if prevW != w || prevH != h {
_ = resizeTty(ctx, cli, id, isExec)
}
prevH = h
prevW = w
}
}()
} else {
sigchan := make(chan os.Signal, 1)
gosignal.Notify(sigchan, signal.SIGWINCH)
go func() {
for range sigchan {
_ = resizeTty(ctx, cli, id, isExec)
}
}()
}
return nil
}