mirror of
https://github.com/containers/podman.git
synced 2026-03-22 08:32:42 -04:00
the compilation demands of having libpod in main is a burden for the remote client compilations. to combat this, we should move the use of libpod structs, vars, constants, and functions into the adapter code where it will only be compiled by the local client. this should result in cleaner code organization and smaller binaries. it should also help if we ever need to compile the remote client on non-Linux operating systems natively (not cross-compiled). Signed-off-by: baude <bbaude@redhat.com>
115 lines
3.2 KiB
Go
115 lines
3.2 KiB
Go
// +build varlink
|
|
|
|
package varlinkapi
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
|
|
"github.com/containers/libpod/cmd/podman/varlink"
|
|
"github.com/containers/libpod/libpod"
|
|
"github.com/containers/libpod/libpod/define"
|
|
"github.com/containers/libpod/pkg/varlinkapi/virtwriter"
|
|
"github.com/sirupsen/logrus"
|
|
"k8s.io/client-go/tools/remotecommand"
|
|
)
|
|
|
|
func setupStreams(call iopodman.VarlinkCall) (*bufio.Reader, *bufio.Writer, *io.PipeReader, *io.PipeWriter, *libpod.AttachStreams) {
|
|
|
|
// These are the varlink sockets
|
|
reader := call.Call.Reader
|
|
writer := call.Call.Writer
|
|
|
|
// This pipe is used to pass stdin from the client to the input stream
|
|
// once the msg has been "decoded"
|
|
pr, pw := io.Pipe()
|
|
|
|
stdoutWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.ToStdout)
|
|
// TODO if runc ever starts passing stderr, we can too
|
|
//stderrWriter := NewVirtWriteCloser(writer, ToStderr)
|
|
|
|
streams := libpod.AttachStreams{
|
|
OutputStream: stdoutWriter,
|
|
InputStream: pr,
|
|
// Runc eats the error stream
|
|
ErrorStream: stdoutWriter,
|
|
AttachInput: true,
|
|
AttachOutput: true,
|
|
// Runc eats the error stream
|
|
AttachError: true,
|
|
}
|
|
return reader, writer, pr, pw, &streams
|
|
}
|
|
|
|
// Attach connects to a containers console
|
|
func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys string, start bool) error {
|
|
var finalErr error
|
|
resize := make(chan remotecommand.TerminalSize)
|
|
errChan := make(chan error)
|
|
|
|
if !call.WantsUpgrade() {
|
|
return call.ReplyErrorOccurred("client must use upgraded connection to attach")
|
|
}
|
|
ctr, err := i.Runtime.LookupContainer(name)
|
|
if err != nil {
|
|
return call.ReplyErrorOccurred(err.Error())
|
|
}
|
|
state, err := ctr.State()
|
|
if err != nil {
|
|
return call.ReplyErrorOccurred(err.Error())
|
|
}
|
|
if !start && state != libpod.ContainerStateRunning {
|
|
return call.ReplyErrorOccurred("container must be running to attach")
|
|
}
|
|
|
|
// ACK the client upgrade request
|
|
call.ReplyAttach()
|
|
|
|
reader, writer, _, pw, streams := setupStreams(call)
|
|
|
|
go func() {
|
|
if err := virtwriter.Reader(reader, nil, nil, pw, resize); err != nil {
|
|
errChan <- err
|
|
}
|
|
}()
|
|
|
|
if state == libpod.ContainerStateRunning {
|
|
finalErr = attach(ctr, streams, detachKeys, resize, errChan)
|
|
} else {
|
|
finalErr = startAndAttach(ctr, streams, detachKeys, resize, errChan)
|
|
}
|
|
|
|
if finalErr != define.ErrDetach && finalErr != nil {
|
|
logrus.Error(finalErr)
|
|
}
|
|
quitWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.Quit)
|
|
_, err = quitWriter.Write([]byte("HANG-UP"))
|
|
// TODO error handling is not quite right here yet
|
|
return call.Writer.Flush()
|
|
}
|
|
|
|
func attach(ctr *libpod.Container, streams *libpod.AttachStreams, detachKeys string, resize chan remotecommand.TerminalSize, errChan chan error) error {
|
|
go func() {
|
|
if err := ctr.Attach(streams, detachKeys, resize); err != nil {
|
|
errChan <- err
|
|
}
|
|
}()
|
|
attachError := <-errChan
|
|
return attachError
|
|
}
|
|
|
|
func startAndAttach(ctr *libpod.Container, streams *libpod.AttachStreams, detachKeys string, resize chan remotecommand.TerminalSize, errChan chan error) error {
|
|
var finalErr error
|
|
attachChan, err := ctr.StartAndAttach(getContext(), streams, detachKeys, resize, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
select {
|
|
case attachChanErr := <-attachChan:
|
|
finalErr = attachChanErr
|
|
case chanError := <-errChan:
|
|
finalErr = chanError
|
|
}
|
|
return finalErr
|
|
}
|