Merge pull request #579 from alexlarsson/non-terminal-attach
Implement non-terminal attach
This commit is contained in:
commit
7b9032bac7
8 changed files with 143 additions and 42 deletions
|
@ -3,14 +3,12 @@ package server
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/pools"
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/kubernetes-incubator/cri-o/utils"
|
||||
"golang.org/x/net/context"
|
||||
|
@ -19,6 +17,13 @@ import (
|
|||
"k8s.io/kubernetes/pkg/util/term"
|
||||
)
|
||||
|
||||
/* Sync with stdpipe_t in conmon.c */
|
||||
const (
|
||||
AttachPipeStdin = 1
|
||||
AttachPipeStdout = 2
|
||||
AttachPipeStderr = 3
|
||||
)
|
||||
|
||||
// Attach prepares a streaming endpoint to attach to a running container.
|
||||
func (s *Server) Attach(ctx context.Context, req *pb.AttachRequest) (*pb.AttachResponse, error) {
|
||||
logrus.Debugf("AttachRequest %+v", req)
|
||||
|
@ -63,7 +68,7 @@ func (ss streamService) Attach(containerID string, inputStream io.Reader, output
|
|||
})
|
||||
|
||||
attachSocketPath := filepath.Join("/var/run/crio", c.ID(), "attach")
|
||||
conn, err := net.Dial("unix", attachSocketPath)
|
||||
conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: attachSocketPath, Net: "unixpacket"})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to container %s attach socket: %v", c.ID(), err)
|
||||
}
|
||||
|
@ -72,7 +77,7 @@ func (ss streamService) Attach(containerID string, inputStream io.Reader, output
|
|||
receiveStdout := make(chan error)
|
||||
if outputStream != nil || errorStream != nil {
|
||||
go func() {
|
||||
receiveStdout <- redirectResponseToOutputStream(tty, outputStream, errorStream, conn)
|
||||
receiveStdout <- redirectResponseToOutputStreams(outputStream, errorStream, conn)
|
||||
}()
|
||||
}
|
||||
|
||||
|
@ -81,6 +86,7 @@ func (ss streamService) Attach(containerID string, inputStream io.Reader, output
|
|||
var err error
|
||||
if inputStream != nil {
|
||||
_, err = utils.CopyDetachable(conn, inputStream, nil)
|
||||
conn.CloseWrite()
|
||||
}
|
||||
stdinDone <- err
|
||||
}()
|
||||
|
@ -100,18 +106,42 @@ func (ss streamService) Attach(containerID string, inputStream io.Reader, output
|
|||
return nil
|
||||
}
|
||||
|
||||
func redirectResponseToOutputStream(tty bool, outputStream, errorStream io.Writer, conn io.Reader) error {
|
||||
if outputStream == nil {
|
||||
outputStream = ioutil.Discard
|
||||
}
|
||||
if errorStream == nil {
|
||||
// errorStream = ioutil.Discard
|
||||
}
|
||||
func redirectResponseToOutputStreams(outputStream, errorStream io.Writer, conn io.Reader) error {
|
||||
var err error
|
||||
if tty {
|
||||
_, err = pools.Copy(outputStream, conn)
|
||||
} else {
|
||||
// TODO
|
||||
buf := make([]byte, 8192+1) /* Sync with conmon STDIO_BUF_SIZE */
|
||||
|
||||
for {
|
||||
nr, er := conn.Read(buf)
|
||||
if nr > 0 {
|
||||
var dst io.Writer
|
||||
if buf[0] == AttachPipeStdout {
|
||||
dst = outputStream
|
||||
} else if buf[0] == AttachPipeStderr {
|
||||
dst = errorStream
|
||||
} else {
|
||||
logrus.Infof("Got unexpected attach type %+d", buf[0])
|
||||
}
|
||||
|
||||
if dst != nil {
|
||||
nw, ew := dst.Write(buf[1:nr])
|
||||
if ew != nil {
|
||||
err = ew
|
||||
break
|
||||
}
|
||||
if nr != nw+1 {
|
||||
err = io.ErrShortWrite
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if er == io.EOF {
|
||||
break
|
||||
}
|
||||
if er != nil {
|
||||
err = er
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -537,6 +537,8 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
|
|||
specgen.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer)
|
||||
specgen.AddAnnotation(annotations.LogPath, logPath)
|
||||
specgen.AddAnnotation(annotations.TTY, fmt.Sprintf("%v", containerConfig.Tty))
|
||||
specgen.AddAnnotation(annotations.Stdin, fmt.Sprintf("%v", containerConfig.Stdin))
|
||||
specgen.AddAnnotation(annotations.StdinOnce, fmt.Sprintf("%v", containerConfig.StdinOnce))
|
||||
specgen.AddAnnotation(annotations.Image, image)
|
||||
|
||||
created := time.Now()
|
||||
|
@ -671,7 +673,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
container, err := oci.NewContainer(containerID, containerName, containerInfo.RunDir, logPath, sb.netNs(), labels, kubeAnnotations, imageSpec, metadata, sb.id, containerConfig.Tty, sb.privileged, containerInfo.Dir, created, containerImageConfig.Config.StopSignal)
|
||||
container, err := oci.NewContainer(containerID, containerName, containerInfo.RunDir, logPath, sb.netNs(), labels, kubeAnnotations, imageSpec, metadata, sb.id, containerConfig.Tty, containerConfig.Stdin, containerConfig.StdinOnce, sb.privileged, containerInfo.Dir, created, containerImageConfig.Config.StopSignal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -438,7 +438,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
|
|||
return nil, fmt.Errorf("failed to write runtime configuration for pod sandbox %s(%s): %v", sb.name, id, err)
|
||||
}
|
||||
|
||||
container, err := oci.NewContainer(id, containerName, podContainer.RunDir, logPath, sb.netNs(), labels, kubeAnnotations, nil, nil, id, false, sb.privileged, podContainer.Dir, created, podContainer.Config.Config.StopSignal)
|
||||
container, err := oci.NewContainer(id, containerName, podContainer.RunDir, logPath, sb.netNs(), labels, kubeAnnotations, nil, nil, id, false, false, false, sb.privileged, podContainer.Dir, created, podContainer.Config.Config.StopSignal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ const (
|
|||
shutdownFile = "/var/lib/crio/crio.shutdown"
|
||||
)
|
||||
|
||||
func isTrue(annotaton string) bool {
|
||||
return annotaton == "true"
|
||||
}
|
||||
|
||||
// streamService implements streaming.Runtime.
|
||||
type streamService struct {
|
||||
runtimeServer *Server // needed by Exec() endpoint
|
||||
|
@ -116,10 +120,10 @@ func (s *Server) loadContainer(id string) error {
|
|||
return fmt.Errorf("could not get sandbox with id %s, skipping", m.Annotations[annotations.SandboxID])
|
||||
}
|
||||
|
||||
var tty bool
|
||||
if v := m.Annotations[annotations.TTY]; v == "true" {
|
||||
tty = true
|
||||
}
|
||||
tty := isTrue(m.Annotations[annotations.TTY])
|
||||
stdin := isTrue(m.Annotations[annotations.Stdin])
|
||||
stdinOnce := isTrue(m.Annotations[annotations.StdinOnce])
|
||||
|
||||
containerPath, err := s.store.ContainerRunDirectory(id)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -148,7 +152,7 @@ func (s *Server) loadContainer(id string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations[annotations.LogPath], sb.netNs(), labels, kubeAnnotations, img, &metadata, sb.id, tty, sb.privileged, containerDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
|
||||
ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations[annotations.LogPath], sb.netNs(), labels, kubeAnnotations, img, &metadata, sb.id, tty, stdin, stdinOnce, sb.privileged, containerDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -238,7 +242,7 @@ func (s *Server) loadSandbox(id string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
privileged := m.Annotations[annotations.PrivilegedRuntime] == "true"
|
||||
privileged := isTrue(m.Annotations[annotations.PrivilegedRuntime])
|
||||
|
||||
sb := &sandbox{
|
||||
id: id,
|
||||
|
@ -304,7 +308,7 @@ func (s *Server) loadSandbox(id string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
scontainer, err := oci.NewContainer(m.Annotations[annotations.ContainerID], cname, sandboxPath, m.Annotations[annotations.LogPath], sb.netNs(), labels, kubeAnnotations, nil, nil, id, false, privileged, sandboxDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
|
||||
scontainer, err := oci.NewContainer(m.Annotations[annotations.ContainerID], cname, sandboxPath, m.Annotations[annotations.LogPath], sb.netNs(), labels, kubeAnnotations, nil, nil, id, false, false, false, privileged, sandboxDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue