Fix terminal resize handling so kubectl exec -i -t sh works
Signed-off-by: Mrunal Patel <mpatel@redhat.com>
This commit is contained in:
parent
c676b7b6c3
commit
008dab27b1
1 changed files with 61 additions and 11 deletions
|
@ -3,12 +3,15 @@ package server
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/kubernetes-incubator/cri-o/oci"
|
"github.com/kubernetes-incubator/cri-o/oci"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||||
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||||
|
utilexec "k8s.io/kubernetes/pkg/util/exec"
|
||||||
"k8s.io/kubernetes/pkg/util/term"
|
"k8s.io/kubernetes/pkg/util/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,8 +28,8 @@ func (s *Server) Exec(ctx context.Context, req *pb.ExecRequest) (*pb.ExecRespons
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec endpoint for streaming.Runtime
|
// Exec endpoint for streaming.Runtime
|
||||||
func (ss streamService) Exec(containerID string, cmd []string, in io.Reader, out, errOut io.WriteCloser, tty bool, resize <-chan term.Size) error {
|
func (ss streamService) Exec(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) error {
|
||||||
fmt.Println(containerID, cmd, in, out, errOut, tty, resize)
|
fmt.Println(containerID, cmd, stdin, stdout, stderr, tty, resize)
|
||||||
c := ss.runtimeServer.state.containers.Get(containerID)
|
c := ss.runtimeServer.state.containers.Get(containerID)
|
||||||
|
|
||||||
if err := ss.runtimeServer.runtime.UpdateStatus(c); err != nil {
|
if err := ss.runtimeServer.runtime.UpdateStatus(c); err != nil {
|
||||||
|
@ -38,16 +41,63 @@ func (ss streamService) Exec(containerID string, cmd []string, in io.Reader, out
|
||||||
return fmt.Errorf("container is not created or running")
|
return fmt.Errorf("container is not created or running")
|
||||||
}
|
}
|
||||||
|
|
||||||
args := []string{"exec", c.Name()} // exec ctr
|
args := []string{"exec"}
|
||||||
args = append(args, cmd...) // exec ctr cmd
|
if tty {
|
||||||
execCmd := exec.Command(ss.runtimeServer.runtime.Path(c), args...) // runc exec ctr cmd
|
args = append(args, "-t")
|
||||||
execCmd.Stdin = in
|
}
|
||||||
execCmd.Stdout = out
|
args = append(args, c.Name())
|
||||||
execCmd.Stderr = errOut
|
args = append(args, cmd...)
|
||||||
|
execCmd := exec.Command(ss.runtimeServer.runtime.Path(c), args...)
|
||||||
|
var cmdErr error
|
||||||
|
if tty {
|
||||||
|
p, err := kubecontainer.StartPty(execCmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
if err := execCmd.Run(); err != nil {
|
// make sure to close the stdout stream
|
||||||
return err
|
defer stdout.Close()
|
||||||
|
|
||||||
|
kubecontainer.HandleResizing(resize, func(size term.Size) {
|
||||||
|
term.SetSize(p.Fd(), size)
|
||||||
|
})
|
||||||
|
|
||||||
|
if stdin != nil {
|
||||||
|
go io.Copy(p, stdin)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdout != nil {
|
||||||
|
go io.Copy(stdout, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdErr = execCmd.Wait()
|
||||||
|
} else {
|
||||||
|
if stdin != nil {
|
||||||
|
// Use an os.Pipe here as it returns true *os.File objects.
|
||||||
|
// This way, if you run 'kubectl exec <pod> -i bash' (no tty) and type 'exit',
|
||||||
|
// the call below to execCmd.Run() can unblock because its Stdin is the read half
|
||||||
|
// of the pipe.
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go io.Copy(w, stdin)
|
||||||
|
|
||||||
|
execCmd.Stdin = r
|
||||||
|
}
|
||||||
|
if stdout != nil {
|
||||||
|
execCmd.Stdout = stdout
|
||||||
|
}
|
||||||
|
if stderr != nil {
|
||||||
|
execCmd.Stderr = stderr
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdErr = execCmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if exitErr, ok := cmdErr.(*exec.ExitError); ok {
|
||||||
|
return &utilexec.ExitErrorWrapper{ExitError: exitErr}
|
||||||
|
}
|
||||||
|
return cmdErr
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue