2016-09-08 13:11:39 -04:00
|
|
|
package container
|
|
|
|
|
|
|
|
import (
|
2018-05-03 21:02:44 -04:00
|
|
|
"context"
|
2016-09-08 13:11:39 -04:00
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
gosignal "os/signal"
|
|
|
|
"runtime"
|
|
|
|
"time"
|
|
|
|
|
2017-04-17 18:07:56 -04:00
|
|
|
"github.com/docker/cli/cli/command"
|
2023-10-13 14:34:32 -04:00
|
|
|
"github.com/docker/docker/api/types/container"
|
2017-05-08 13:51:30 -04:00
|
|
|
"github.com/docker/docker/client"
|
2021-08-09 13:15:46 -04:00
|
|
|
"github.com/moby/sys/signal"
|
2017-08-07 05:52:40 -04:00
|
|
|
"github.com/sirupsen/logrus"
|
2016-09-08 13:11:39 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// resizeTtyTo resizes tty to specific height and width
|
2023-11-20 11:38:50 -05:00
|
|
|
func resizeTtyTo(ctx context.Context, apiClient client.ContainerAPIClient, id string, height, width uint, isExec bool) error {
|
2016-09-08 13:11:39 -04:00
|
|
|
if height == 0 && width == 0 {
|
2018-11-21 08:41:51 -05:00
|
|
|
return nil
|
2016-09-08 13:11:39 -04:00
|
|
|
}
|
|
|
|
|
2023-10-13 14:34:32 -04:00
|
|
|
options := container.ResizeOptions{
|
2016-09-08 13:11:39 -04:00
|
|
|
Height: height,
|
|
|
|
Width: width,
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
|
|
|
if isExec {
|
2023-11-20 11:38:50 -05:00
|
|
|
err = apiClient.ContainerExecResize(ctx, id, options)
|
2016-09-08 13:11:39 -04:00
|
|
|
} else {
|
2023-11-20 11:38:50 -05:00
|
|
|
err = apiClient.ContainerResize(ctx, id, options)
|
2016-09-08 13:11:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
2018-11-21 08:41:51 -05:00
|
|
|
logrus.Debugf("Error resize: %s\r", err)
|
2016-09-08 13:11:39 -04:00
|
|
|
}
|
2018-11-21 08:41:51 -05:00
|
|
|
return err
|
2016-09-08 13:11:39 -04:00
|
|
|
}
|
|
|
|
|
2018-11-21 08:41:51 -05:00
|
|
|
// 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)
|
|
|
|
}
|
2016-09-08 13:11:39 -04:00
|
|
|
|
2022-04-28 08:55:01 -04:00
|
|
|
// initTtySize is to init the tty's size to the same as the window, if there is an error, it will retry 10 times.
|
2018-11-21 08:41:51 -05:00
|
|
|
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
|
2022-04-28 08:55:01 -04:00
|
|
|
for retry := 0; retry < 10; retry++ {
|
|
|
|
time.Sleep(time.Duration(retry+1) * 10 * time.Millisecond)
|
2018-11-21 08:41:51 -05:00
|
|
|
if err = rttyFunc(ctx, cli, id, isExec); err == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(cli.Err(), "failed to resize tty, using default size")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
2016-09-08 13:11:39 -04:00
|
|
|
|
2018-11-21 08:41:51 -05:00
|
|
|
// 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)
|
2016-09-08 13:11:39 -04:00
|
|
|
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 {
|
2018-11-21 08:41:51 -05:00
|
|
|
resizeTty(ctx, cli, id, isExec)
|
2016-09-08 13:11:39 -04:00
|
|
|
}
|
|
|
|
prevH = h
|
|
|
|
prevW = w
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
sigchan := make(chan os.Signal, 1)
|
|
|
|
gosignal.Notify(sigchan, signal.SIGWINCH)
|
|
|
|
go func() {
|
|
|
|
for range sigchan {
|
2018-11-21 08:41:51 -05:00
|
|
|
resizeTty(ctx, cli, id, isExec)
|
2016-09-08 13:11:39 -04:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|