From 4d895dcb5472da19b886ca1662182556242fe5d4 Mon Sep 17 00:00:00 2001
From: Brent Baude <bbaude@redhat.com>
Date: Fri, 3 Apr 2020 14:56:10 -0500
Subject: v2podman attach and exec

add the ability to attach to a running container.  the tunnel side of this is not enabled yet as we have work on the endpoints and plumbing to do yet.

add the ability to exec a command in a running container.  the tunnel side is also being deferred for same reason.

Signed-off-by: Brent Baude <bbaude@redhat.com>
---
 libpod/container_api.go          | 24 ++----------------------
 libpod/container_exec.go         |  4 ++--
 libpod/container_top_linux.go    |  2 +-
 libpod/define/config.go          | 24 ++++++++++++++++++++++++
 libpod/healthcheck.go            |  2 +-
 libpod/oci.go                    |  4 +++-
 libpod/oci_attach_linux.go       |  8 ++++----
 libpod/oci_attach_unsupported.go |  4 ++--
 8 files changed, 39 insertions(+), 33 deletions(-)

(limited to 'libpod')

diff --git a/libpod/container_api.go b/libpod/container_api.go
index 967180437..55c79fa74 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -3,7 +3,6 @@ package libpod
 import (
 	"bufio"
 	"context"
-	"io"
 	"io/ioutil"
 	"net"
 	"os"
@@ -96,7 +95,7 @@ func (c *Container) Start(ctx context.Context, recursive bool) (err error) {
 // The channel will be closed automatically after the result of attach has been
 // sent.
 // If recursive is set, StartAndAttach will also start all containers this container depends on.
-func (c *Container) StartAndAttach(ctx context.Context, streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, recursive bool) (attachResChan <-chan error, err error) {
+func (c *Container) StartAndAttach(ctx context.Context, streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, recursive bool) (attachResChan <-chan error, err error) {
 	if !c.batched {
 		c.lock.Lock()
 		defer c.lock.Unlock()
@@ -213,29 +212,10 @@ func (c *Container) Kill(signal uint) error {
 	return c.save()
 }
 
-// AttachStreams contains streams that will be attached to the container
-type AttachStreams struct {
-	// OutputStream will be attached to container's STDOUT
-	OutputStream io.WriteCloser
-	// ErrorStream will be attached to container's STDERR
-	ErrorStream io.WriteCloser
-	// InputStream will be attached to container's STDIN
-	InputStream *bufio.Reader
-	// AttachOutput is whether to attach to STDOUT
-	// If false, stdout will not be attached
-	AttachOutput bool
-	// AttachError is whether to attach to STDERR
-	// If false, stdout will not be attached
-	AttachError bool
-	// AttachInput is whether to attach to STDIN
-	// If false, stdout will not be attached
-	AttachInput bool
-}
-
 // Attach attaches to a container.
 // This function returns when the attach finishes. It does not hold the lock for
 // the duration of its runtime, only using it at the beginning to verify state.
-func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize) error {
+func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize) error {
 	if !c.batched {
 		c.lock.Lock()
 		if err := c.syncContainer(); err != nil {
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index 5469462f8..c1ce8b724 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -221,7 +221,7 @@ func (c *Container) ExecStart(sessionID string) error {
 // ExecStartAndAttach starts and attaches to an exec session in a container.
 // TODO: Should we include detach keys in the signature to allow override?
 // TODO: How do we handle AttachStdin/AttachStdout/AttachStderr?
-func (c *Container) ExecStartAndAttach(sessionID string, streams *AttachStreams) error {
+func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachStreams) error {
 	if !c.batched {
 		c.lock.Lock()
 		defer c.lock.Unlock()
@@ -544,7 +544,7 @@ func (c *Container) ExecResize(sessionID string, newSize remotecommand.TerminalS
 // Exec emulates the old Libpod exec API, providing a single call to create,
 // run, and remove an exec session. Returns exit code and error. Exit code is
 // not guaranteed to be set sanely if error is not nil.
-func (c *Container) Exec(config *ExecConfig, streams *AttachStreams, resize <-chan remotecommand.TerminalSize) (int, error) {
+func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resize <-chan remotecommand.TerminalSize) (int, error) {
 	sessionID, err := c.ExecCreate(config)
 	if err != nil {
 		return -1, err
diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go
index 2a35a2ae9..98a69966a 100644
--- a/libpod/container_top_linux.go
+++ b/libpod/container_top_linux.go
@@ -112,7 +112,7 @@ func (c *Container) execPS(args []string) ([]string, error) {
 	defer wErrPipe.Close()
 	defer rErrPipe.Close()
 
-	streams := new(AttachStreams)
+	streams := new(define.AttachStreams)
 	streams.OutputStream = wPipe
 	streams.ErrorStream = wErrPipe
 	streams.AttachOutput = true
diff --git a/libpod/define/config.go b/libpod/define/config.go
index 7b967f17d..10e00062a 100644
--- a/libpod/define/config.go
+++ b/libpod/define/config.go
@@ -1,5 +1,10 @@
 package define
 
+import (
+	"bufio"
+	"io"
+)
+
 var (
 	// DefaultInfraImage to use for infra container
 	DefaultInfraImage = "k8s.gcr.io/pause:3.2"
@@ -33,3 +38,22 @@ const (
 	V2s2ManifestDir = "docker-dir"
 	V2s2Archive     = "docker-archive"
 )
+
+// AttachStreams contains streams that will be attached to the container
+type AttachStreams struct {
+	// OutputStream will be attached to container's STDOUT
+	OutputStream io.WriteCloser
+	// ErrorStream will be attached to container's STDERR
+	ErrorStream io.WriteCloser
+	// InputStream will be attached to container's STDIN
+	InputStream *bufio.Reader
+	// AttachOutput is whether to attach to STDOUT
+	// If false, stdout will not be attached
+	AttachOutput bool
+	// AttachError is whether to attach to STDERR
+	// If false, stdout will not be attached
+	AttachError bool
+	// AttachInput is whether to attach to STDIN
+	// If false, stdout will not be attached
+	AttachInput bool
+}
diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go
index 08a613dfe..daddb6561 100644
--- a/libpod/healthcheck.go
+++ b/libpod/healthcheck.go
@@ -108,7 +108,7 @@ func (c *Container) runHealthCheck() (HealthCheckStatus, error) {
 	hcw := hcWriteCloser{
 		captureBuffer,
 	}
-	streams := new(AttachStreams)
+	streams := new(define.AttachStreams)
 	streams.OutputStream = hcw
 	streams.ErrorStream = hcw
 
diff --git a/libpod/oci.go b/libpod/oci.go
index ef46cf5c3..e4fbcb62e 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -4,6 +4,8 @@ import (
 	"bufio"
 	"net"
 
+	"github.com/containers/libpod/libpod/define"
+
 	"k8s.io/client-go/tools/remotecommand"
 )
 
@@ -141,7 +143,7 @@ type ExecOptions struct {
 	// the container was run as will be used.
 	User string
 	// Streams are the streams that will be attached to the container.
-	Streams *AttachStreams
+	Streams *define.AttachStreams
 	// PreserveFDs is a number of additional file descriptors (in addition
 	// to 0, 1, 2) that will be passed to the executed process. The total FDs
 	// passed will be 3 + PreserveFDs.
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index fb0a54bff..ff158c2d1 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -31,7 +31,7 @@ const (
 // Attach to the given container
 // Does not check if state is appropriate
 // started is only required if startContainer is true
-func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
+func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
 	if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
 		return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
 	}
@@ -94,7 +94,7 @@ func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan re
 // 4. attachToExec sends on startFd, signalling it has attached to the socket and child is ready to go
 // 5. child receives on startFd, runs the runtime exec command
 // attachToExec is responsible for closing startFd and attachFd
-func (c *Container) attachToExec(streams *AttachStreams, keys *string, sessionID string, startFd, attachFd *os.File) error {
+func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, sessionID string, startFd, attachFd *os.File) error {
 	if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
 		return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
 	}
@@ -189,7 +189,7 @@ func buildSocketPath(socketPath string) string {
 	return socketPath
 }
 
-func setupStdioChannels(streams *AttachStreams, conn *net.UnixConn, detachKeys []byte) (chan error, chan error) {
+func setupStdioChannels(streams *define.AttachStreams, conn *net.UnixConn, detachKeys []byte) (chan error, chan error) {
 	receiveStdoutError := make(chan error)
 	go func() {
 		receiveStdoutError <- redirectResponseToOutputStreams(streams.OutputStream, streams.ErrorStream, streams.AttachOutput, streams.AttachError, conn)
@@ -257,7 +257,7 @@ func redirectResponseToOutputStreams(outputStream, errorStream io.Writer, writeO
 	return err
 }
 
-func readStdio(streams *AttachStreams, receiveStdoutError, stdinDone chan error) error {
+func readStdio(streams *define.AttachStreams, receiveStdoutError, stdinDone chan error) error {
 	var err error
 	select {
 	case err = <-receiveStdoutError:
diff --git a/libpod/oci_attach_unsupported.go b/libpod/oci_attach_unsupported.go
index 987d2c973..3b0216e5d 100644
--- a/libpod/oci_attach_unsupported.go
+++ b/libpod/oci_attach_unsupported.go
@@ -9,10 +9,10 @@ import (
 	"k8s.io/client-go/tools/remotecommand"
 )
 
-func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
+func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
 	return define.ErrNotImplemented
 }
 
-func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, sessionID string, startFd *os.File, attachFd *os.File) error {
+func (c *Container) attachToExec(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, sessionID string, startFd *os.File, attachFd *os.File) error {
 	return define.ErrNotImplemented
 }
-- 
cgit v1.2.3-54-g00ecf