Decouple term and remotecommand packages
This allows consumers of term to not pull in dependencies on github.com/gorilla/websocket and github.com/moby/spdystream. Kubernetes-commit: 640dabd58b04b72f646ed85947cb8b407b36dc08
This commit is contained in:
parent
22d999d2fc
commit
ce4d90902a
|
@ -42,6 +42,7 @@ import (
|
||||||
"k8s.io/kubectl/pkg/util/completion"
|
"k8s.io/kubectl/pkg/util/completion"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
"k8s.io/kubectl/pkg/util/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -300,7 +301,9 @@ func (o *AttachOptions) Run() error {
|
||||||
sizePlusOne.Height++
|
sizePlusOne.Height++
|
||||||
|
|
||||||
// this call spawns a goroutine to monitor/update the terminal size
|
// 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
|
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)
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -366,7 +366,9 @@ func (p *ExecOptions) Run() error {
|
||||||
var sizeQueue remotecommand.TerminalSizeQueue
|
var sizeQueue remotecommand.TerminalSizeQueue
|
||||||
if t.Raw {
|
if t.Raw {
|
||||||
// this call spawns a goroutine to monitor/update the terminal size
|
// 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
|
// unset p.Err if it was previously set because both stdout and stderr go over p.Out when tty is
|
||||||
// true
|
// true
|
||||||
|
@ -403,3 +405,18 @@ func (p *ExecOptions) Run() error {
|
||||||
|
|
||||||
return nil
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,12 +21,28 @@ import (
|
||||||
|
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"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,
|
// GetSize returns the current size of the user's terminal. If it isn't a terminal,
|
||||||
// nil is returned.
|
// nil is returned.
|
||||||
func (t TTY) GetSize() *remotecommand.TerminalSize {
|
func (t TTY) GetSize() *TerminalSize {
|
||||||
outFd, isTerminal := term.GetFdInfo(t.Out)
|
outFd, isTerminal := term.GetFdInfo(t.Out)
|
||||||
if !isTerminal {
|
if !isTerminal {
|
||||||
return nil
|
return nil
|
||||||
|
@ -35,19 +51,19 @@ func (t TTY) GetSize() *remotecommand.TerminalSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSize returns the current size of the terminal associated with fd.
|
// 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)
|
winsize, err := term.GetWinsize(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err))
|
runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err))
|
||||||
return nil
|
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
|
// MonitorSize monitors the terminal's size. It returns a TerminalSizeQueue primed with
|
||||||
// initialSizes, or nil if there's no TTY present.
|
// 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)
|
outFd, isTerminal := term.GetFdInfo(t.Out)
|
||||||
if !isTerminal {
|
if !isTerminal {
|
||||||
return nil
|
return nil
|
||||||
|
@ -57,7 +73,7 @@ func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecom
|
||||||
t: *t,
|
t: *t,
|
||||||
// make it buffered so we can send the initial terminal sizes without blocking, prior to starting
|
// make it buffered so we can send the initial terminal sizes without blocking, prior to starting
|
||||||
// the streaming below
|
// the streaming below
|
||||||
resizeChan: make(chan remotecommand.TerminalSize, len(initialSizes)),
|
resizeChan: make(chan TerminalSize, len(initialSizes)),
|
||||||
stopResizing: make(chan struct{}),
|
stopResizing: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,16 +86,16 @@ func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecom
|
||||||
type sizeQueue struct {
|
type sizeQueue struct {
|
||||||
t TTY
|
t TTY
|
||||||
// resizeChan receives a Size each time the user's terminal is resized.
|
// resizeChan receives a Size each time the user's terminal is resized.
|
||||||
resizeChan chan remotecommand.TerminalSize
|
resizeChan chan TerminalSize
|
||||||
stopResizing chan struct{}
|
stopResizing chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure sizeQueue implements the resize.TerminalSizeQueue interface
|
// make sure sizeQueue implements the TerminalSizeQueue interface
|
||||||
var _ remotecommand.TerminalSizeQueue = &sizeQueue{}
|
var _ TerminalSizeQueue = &sizeQueue{}
|
||||||
|
|
||||||
// monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each
|
// monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each
|
||||||
// new event, it sends the current terminal size to resizeChan.
|
// 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
|
// send the initial sizes
|
||||||
for i := range initialSizes {
|
for i := range initialSizes {
|
||||||
if initialSizes[i] != nil {
|
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)
|
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
|
// Next returns the new terminal size after the terminal has been resized. It returns nil when
|
||||||
// monitoring has been stopped.
|
// monitoring has been stopped.
|
||||||
func (s *sizeQueue) Next() *remotecommand.TerminalSize {
|
func (s *sizeQueue) Next() *TerminalSize {
|
||||||
size, ok := <-s.resizeChan
|
size, ok := <-s.resizeChan
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -25,13 +25,12 @@ import (
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// monitorResizeEvents spawns a goroutine that waits for SIGWINCH signals (these indicate the
|
// 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
|
// 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.
|
// 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() {
|
go func() {
|
||||||
defer runtime.HandleCrash()
|
defer runtime.HandleCrash()
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,12 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"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
|
// 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
|
// it to the resizeEvents channel if the size has changed. The goroutine stops when the stop channel
|
||||||
// is closed.
|
// 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() {
|
go func() {
|
||||||
defer runtime.HandleCrash()
|
defer runtime.HandleCrash()
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,6 @@ import (
|
||||||
|
|
||||||
wordwrap "github.com/mitchellh/go-wordwrap"
|
wordwrap "github.com/mitchellh/go-wordwrap"
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
|
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type wordWrapWriter struct {
|
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
|
var limit uint
|
||||||
switch {
|
switch {
|
||||||
case terminalSize.Width >= 120:
|
case terminalSize.Width >= 120:
|
||||||
|
|
Loading…
Reference in New Issue