diff --git a/pkg/cmd/attach/attach.go b/pkg/cmd/attach/attach.go index caf6ec7f1..62b1f6411 100644 --- a/pkg/cmd/attach/attach.go +++ b/pkg/cmd/attach/attach.go @@ -42,6 +42,7 @@ import ( "k8s.io/kubectl/pkg/util/completion" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" + "k8s.io/kubectl/pkg/util/term" ) var ( @@ -300,7 +301,9 @@ func (o *AttachOptions) Run() error { sizePlusOne.Height++ // this call spawns a goroutine to monitor/update the terminal size - sizeQueue = t.MonitorSize(&sizePlusOne, size) + sizeQueue = &terminalSizeQueueAdapter{ + delegate: t.MonitorSize(&sizePlusOne, size), + } } o.DisableStderr = true @@ -357,3 +360,18 @@ func (o *AttachOptions) reattachMessage(containerName string, rawTTY bool) strin } return fmt.Sprintf("Session ended, resume using '%s %s -c %s -i -t' command when the pod is running", o.CommandName, o.Pod.Name, containerName) } + +type terminalSizeQueueAdapter struct { + delegate term.TerminalSizeQueue +} + +func (a *terminalSizeQueueAdapter) Next() *remotecommand.TerminalSize { + next := a.delegate.Next() + if next == nil { + return nil + } + return &remotecommand.TerminalSize{ + Width: next.Width, + Height: next.Height, + } +} diff --git a/pkg/cmd/exec/exec.go b/pkg/cmd/exec/exec.go index 64773e2ed..ca47976ce 100644 --- a/pkg/cmd/exec/exec.go +++ b/pkg/cmd/exec/exec.go @@ -366,7 +366,9 @@ func (p *ExecOptions) Run() error { var sizeQueue remotecommand.TerminalSizeQueue if t.Raw { // this call spawns a goroutine to monitor/update the terminal size - sizeQueue = t.MonitorSize(t.GetSize()) + sizeQueue = &terminalSizeQueueAdapter{ + delegate: t.MonitorSize(t.GetSize()), + } // unset p.Err if it was previously set because both stdout and stderr go over p.Out when tty is // true @@ -403,3 +405,18 @@ func (p *ExecOptions) Run() error { return nil } + +type terminalSizeQueueAdapter struct { + delegate term.TerminalSizeQueue +} + +func (a *terminalSizeQueueAdapter) Next() *remotecommand.TerminalSize { + next := a.delegate.Next() + if next == nil { + return nil + } + return &remotecommand.TerminalSize{ + Width: next.Width, + Height: next.Height, + } +} diff --git a/pkg/util/term/resize.go b/pkg/util/term/resize.go index 636b8bef4..a38d27f3d 100644 --- a/pkg/util/term/resize.go +++ b/pkg/util/term/resize.go @@ -21,12 +21,28 @@ import ( "github.com/moby/term" "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" ) +// TerminalSize represents the width and height of a terminal. +// It is the same as staging/src/k8s.io/client-go/tools/remotecommand.TerminalSize. +// Copied to decouple the packages. Terminal-related package should not depend on API client and vice versa. +type TerminalSize struct { + Width uint16 + Height uint16 +} + +// TerminalSizeQueue is capable of returning terminal resize events as they occur. +// It is the same as staging/src/k8s.io/client-go/tools/remotecommand.TerminalSizeQueue. +// Copied to decouple the packages. Terminal-related package should not depend on API client and vice versa. +type TerminalSizeQueue interface { + // Next returns the new terminal size after the terminal has been resized. It returns nil when + // monitoring has been stopped. + Next() *TerminalSize +} + // GetSize returns the current size of the user's terminal. If it isn't a terminal, // nil is returned. -func (t TTY) GetSize() *remotecommand.TerminalSize { +func (t TTY) GetSize() *TerminalSize { outFd, isTerminal := term.GetFdInfo(t.Out) if !isTerminal { return nil @@ -35,19 +51,19 @@ func (t TTY) GetSize() *remotecommand.TerminalSize { } // GetSize returns the current size of the terminal associated with fd. -func GetSize(fd uintptr) *remotecommand.TerminalSize { +func GetSize(fd uintptr) *TerminalSize { winsize, err := term.GetWinsize(fd) if err != nil { runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err)) return nil } - return &remotecommand.TerminalSize{Width: winsize.Width, Height: winsize.Height} + return &TerminalSize{Width: winsize.Width, Height: winsize.Height} } // MonitorSize monitors the terminal's size. It returns a TerminalSizeQueue primed with // initialSizes, or nil if there's no TTY present. -func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecommand.TerminalSizeQueue { +func (t *TTY) MonitorSize(initialSizes ...*TerminalSize) TerminalSizeQueue { outFd, isTerminal := term.GetFdInfo(t.Out) if !isTerminal { return nil @@ -57,7 +73,7 @@ func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecom t: *t, // make it buffered so we can send the initial terminal sizes without blocking, prior to starting // the streaming below - resizeChan: make(chan remotecommand.TerminalSize, len(initialSizes)), + resizeChan: make(chan TerminalSize, len(initialSizes)), stopResizing: make(chan struct{}), } @@ -70,16 +86,16 @@ func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecom type sizeQueue struct { t TTY // resizeChan receives a Size each time the user's terminal is resized. - resizeChan chan remotecommand.TerminalSize + resizeChan chan TerminalSize stopResizing chan struct{} } -// make sure sizeQueue implements the resize.TerminalSizeQueue interface -var _ remotecommand.TerminalSizeQueue = &sizeQueue{} +// make sure sizeQueue implements the TerminalSizeQueue interface +var _ TerminalSizeQueue = &sizeQueue{} // monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each // new event, it sends the current terminal size to resizeChan. -func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*remotecommand.TerminalSize) { +func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*TerminalSize) { // send the initial sizes for i := range initialSizes { if initialSizes[i] != nil { @@ -87,7 +103,7 @@ func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*remotecommand.Te } } - resizeEvents := make(chan remotecommand.TerminalSize, 1) + resizeEvents := make(chan TerminalSize, 1) monitorResizeEvents(outFd, resizeEvents, s.stopResizing) @@ -118,7 +134,7 @@ func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*remotecommand.Te // Next returns the new terminal size after the terminal has been resized. It returns nil when // monitoring has been stopped. -func (s *sizeQueue) Next() *remotecommand.TerminalSize { +func (s *sizeQueue) Next() *TerminalSize { size, ok := <-s.resizeChan if !ok { return nil diff --git a/pkg/util/term/resizeevents.go b/pkg/util/term/resizeevents.go index e361b1adb..04b8cdab2 100644 --- a/pkg/util/term/resizeevents.go +++ b/pkg/util/term/resizeevents.go @@ -25,13 +25,12 @@ import ( "golang.org/x/sys/unix" "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" ) // monitorResizeEvents spawns a goroutine that waits for SIGWINCH signals (these indicate the // terminal has resized). After receiving a SIGWINCH, this gets the terminal size and tries to send // it to the resizeEvents channel. The goroutine stops when the stop channel is closed. -func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) { +func monitorResizeEvents(fd uintptr, resizeEvents chan<- TerminalSize, stop chan struct{}) { go func() { defer runtime.HandleCrash() diff --git a/pkg/util/term/resizeevents_windows.go b/pkg/util/term/resizeevents_windows.go index adccf8734..ae930642f 100644 --- a/pkg/util/term/resizeevents_windows.go +++ b/pkg/util/term/resizeevents_windows.go @@ -20,13 +20,12 @@ import ( "time" "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/tools/remotecommand" ) // monitorResizeEvents spawns a goroutine that periodically gets the terminal size and tries to send // it to the resizeEvents channel if the size has changed. The goroutine stops when the stop channel // is closed. -func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) { +func monitorResizeEvents(fd uintptr, resizeEvents chan<- TerminalSize, stop chan struct{}) { go func() { defer runtime.HandleCrash() diff --git a/pkg/util/term/term_writer.go b/pkg/util/term/term_writer.go index e3f600880..df85482fc 100644 --- a/pkg/util/term/term_writer.go +++ b/pkg/util/term/term_writer.go @@ -23,8 +23,6 @@ import ( wordwrap "github.com/mitchellh/go-wordwrap" "github.com/moby/term" - - "k8s.io/client-go/tools/remotecommand" ) type wordWrapWriter struct { @@ -70,7 +68,7 @@ func NewWordWrapWriter(w io.Writer, limit uint) io.Writer { } } -func getTerminalLimitWidth(terminalSize *remotecommand.TerminalSize) uint { +func getTerminalLimitWidth(terminalSize *TerminalSize) uint { var limit uint switch { case terminalSize.Width >= 120: