summaryrefslogtreecommitdiff
path: root/pkg/varlinkapi
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/varlinkapi')
-rw-r--r--pkg/varlinkapi/attach.go4
-rw-r--r--pkg/varlinkapi/containers.go57
-rw-r--r--pkg/varlinkapi/virtwriter/virtwriter.go64
3 files changed, 77 insertions, 48 deletions
diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go
index 97ba525a5..1f8d48eb9 100644
--- a/pkg/varlinkapi/attach.go
+++ b/pkg/varlinkapi/attach.go
@@ -68,7 +68,7 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st
reader, writer, _, pw, streams := setupStreams(call)
go func() {
- if err := virtwriter.Reader(reader, nil, nil, pw, resize); err != nil {
+ if err := virtwriter.Reader(reader, nil, nil, pw, resize, nil); err != nil {
errChan <- err
}
}()
@@ -83,7 +83,7 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st
logrus.Error(finalErr)
}
- if err = virtwriter.HangUp(writer); err != nil {
+ if err = virtwriter.HangUp(writer, 0); err != nil {
logrus.Errorf("Failed to HANG-UP attach to %s: %s", ctr.ID(), err.Error())
}
return call.Writer.Flush()
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index 19a8bfd2e..cd5f305c9 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -782,6 +782,9 @@ func (i *LibpodAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecO
fmt.Sprintf("exec requires a running container, %s is %s", ctr.ID(), state.String()))
}
+ // ACK the client upgrade request
+ call.ReplyExecContainer()
+
envs := []string{}
if opts.Env != nil {
envs = *opts.Env
@@ -797,44 +800,52 @@ func (i *LibpodAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecO
workDir = *opts.Workdir
}
+ var detachKeys string
+ if opts.DetachKeys != nil {
+ detachKeys = *opts.DetachKeys
+ }
+
resizeChan := make(chan remotecommand.TerminalSize)
- errChan := make(chan error)
reader, writer, _, pipeWriter, streams := setupStreams(call)
+ type ExitCodeError struct {
+ ExitCode uint32
+ Error error
+ }
+ ecErrChan := make(chan ExitCodeError, 1)
+
go func() {
- fmt.Printf("ExecContainer Start Reader\n")
- if err := virtwriter.Reader(reader, nil, nil, pipeWriter, resizeChan); err != nil {
- fmt.Printf("ExecContainer Reader err %s, %s\n", err.Error(), errors.Cause(err).Error())
- errChan <- err
+ if err := virtwriter.Reader(reader, nil, nil, pipeWriter, resizeChan, nil); err != nil {
+ ecErrChan <- ExitCodeError{
+ define.ExecErrorCodeGeneric,
+ err,
+ }
}
}()
- // Debugging...
- time.Sleep(5 * time.Second)
-
go func() {
- fmt.Printf("ExecContainer Start ctr.Exec\n")
- // TODO detach keys and resize
- // TODO add handling for exit code
- // TODO capture exit code and return to main thread
- _, err := ctr.Exec(opts.Tty, opts.Privileged, envs, opts.Cmd, user, workDir, streams, 0, nil, "")
+ ec, err := ctr.Exec(opts.Tty, opts.Privileged, envs, opts.Cmd, user, workDir, streams, 0, resizeChan, detachKeys)
if err != nil {
- fmt.Printf("ExecContainer Exec err %s, %s\n", err.Error(), errors.Cause(err).Error())
- errChan <- errors.Wrapf(err, "ExecContainer failed for container %s", ctr.ID())
+ logrus.Errorf(err.Error())
+ }
+ ecErrChan <- ExitCodeError{
+ uint32(ec),
+ err,
}
}()
- execErr := <-errChan
+ ecErr := <-ecErrChan
- if execErr != nil && errors.Cause(execErr) != io.EOF {
- fmt.Printf("ExecContainer err: %s\n", execErr.Error())
- return call.ReplyErrorOccurred(execErr.Error())
- }
+ exitCode := define.TranslateExecErrorToExitCode(int(ecErr.ExitCode), ecErr.Error)
- if err = virtwriter.HangUp(writer); err != nil {
- fmt.Printf("ExecContainer hangup err: %s\n", err.Error())
+ if err = virtwriter.HangUp(writer, uint32(exitCode)); err != nil {
logrus.Errorf("ExecContainer failed to HANG-UP on %s: %s", ctr.ID(), err.Error())
}
- return call.Writer.Flush()
+
+ if err := call.Writer.Flush(); err != nil {
+ logrus.Errorf("Exec Container err: %s", err.Error())
+ }
+
+ return ecErr.Error
}
diff --git a/pkg/varlinkapi/virtwriter/virtwriter.go b/pkg/varlinkapi/virtwriter/virtwriter.go
index 0da2a91fc..27ecd1f52 100644
--- a/pkg/varlinkapi/virtwriter/virtwriter.go
+++ b/pkg/varlinkapi/virtwriter/virtwriter.go
@@ -89,10 +89,14 @@ func (v VirtWriteCloser) Write(input []byte) (int, error) {
}
// Reader decodes the content that comes over the wire and directs it to the proper destination.
-func Reader(r *bufio.Reader, output io.Writer, errput io.Writer, input io.Writer, resize chan remotecommand.TerminalSize) error {
+func Reader(r *bufio.Reader, output, errput, input io.Writer, resize chan remotecommand.TerminalSize, execEcChan chan int) error {
var messageSize int64
headerBytes := make([]byte, 8)
+ if r == nil {
+ return errors.Errorf("Reader must not be nil")
+ }
+
for {
n, err := io.ReadFull(r, headerBytes)
if err != nil {
@@ -106,35 +110,43 @@ func Reader(r *bufio.Reader, output io.Writer, errput io.Writer, input io.Writer
switch IntToSocketDest(int(headerBytes[0])) {
case ToStdout:
- _, err := io.CopyN(output, r, messageSize)
- if err != nil {
- return err
+ if output != nil {
+ _, err := io.CopyN(output, r, messageSize)
+ if err != nil {
+ return err
+ }
}
case ToStderr:
- _, err := io.CopyN(errput, r, messageSize)
- if err != nil {
- return err
+ if errput != nil {
+ _, err := io.CopyN(errput, r, messageSize)
+ if err != nil {
+ return err
+ }
}
case ToStdin:
- _, err := io.CopyN(input, r, messageSize)
- if err != nil {
- return err
- }
- case TerminalResize:
- out := make([]byte, messageSize)
- if messageSize > 0 {
- _, err = io.ReadFull(r, out)
-
+ if input != nil {
+ _, err := io.CopyN(input, r, messageSize)
if err != nil {
return err
}
}
- // Resize events come over in bytes, need to be reserialized
- resizeEvent := remotecommand.TerminalSize{}
- if err := json.Unmarshal(out, &resizeEvent); err != nil {
- return err
+ case TerminalResize:
+ if resize != nil {
+ out := make([]byte, messageSize)
+ if messageSize > 0 {
+ _, err = io.ReadFull(r, out)
+
+ if err != nil {
+ return err
+ }
+ }
+ // Resize events come over in bytes, need to be reserialized
+ resizeEvent := remotecommand.TerminalSize{}
+ if err := json.Unmarshal(out, &resizeEvent); err != nil {
+ return err
+ }
+ resize <- resizeEvent
}
- resize <- resizeEvent
case Quit:
out := make([]byte, messageSize)
if messageSize > 0 {
@@ -144,6 +156,10 @@ func Reader(r *bufio.Reader, output io.Writer, errput io.Writer, input io.Writer
return err
}
}
+ if execEcChan != nil {
+ ecInt := binary.BigEndian.Uint32(out)
+ execEcChan <- int(ecInt)
+ }
return nil
default:
@@ -154,9 +170,11 @@ func Reader(r *bufio.Reader, output io.Writer, errput io.Writer, input io.Writer
}
// HangUp sends message to peer to close connection
-func HangUp(writer *bufio.Writer) (err error) {
+func HangUp(writer *bufio.Writer, ec uint32) (err error) {
n := 0
- msg := []byte("HANG-UP")
+ msg := make([]byte, 4)
+
+ binary.BigEndian.PutUint32(msg, ec)
writeQuit := NewVirtWriteCloser(writer, Quit)
if n, err = writeQuit.Write(msg); err != nil {