aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2018-04-12 12:26:51 -0400
committerAtomic Bot <atomic-devel@projectatomic.io>2018-04-13 18:43:44 +0000
commit8d7635b1ac3eaea83fcf481994294eb137110e96 (patch)
tree9b78bbbeb9b33005c2f29b4fc248d3e7b2ddbf16
parent6609d555f75568bb4f1394736a3e3b31e5f0d355 (diff)
downloadpodman-8d7635b1ac3eaea83fcf481994294eb137110e96.tar.gz
podman-8d7635b1ac3eaea83fcf481994294eb137110e96.tar.bz2
podman-8d7635b1ac3eaea83fcf481994294eb137110e96.zip
Change attach to accept a struct containing streams
Comparing Go interfaces, like io.Reader, to nil does not work. As such, we need to include a bool with each stream telling whether to attach to it. Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #608 Approved by: baude
-rw-r--r--cmd/podman/utils.go48
-rw-r--r--libpod/container_api.go9
-rw-r--r--libpod/container_attach.go39
3 files changed, 78 insertions, 18 deletions
diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go
index 0238fc9c2..925674474 100644
--- a/cmd/podman/utils.go
+++ b/cmd/podman/utils.go
@@ -73,7 +73,7 @@ func attachCtr(ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys
// Check if we are attached to a terminal. If we are, generate resize
// events, and set the terminal to raw mode
- if haveTerminal {
+ if haveTerminal && ctr.Spec().Process.Terminal {
logrus.Debugf("Handling terminal attach")
resizeTty(resize)
@@ -88,11 +88,32 @@ func attachCtr(ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys
defer term.RestoreTerminal(os.Stdin.Fd(), oldTermState)
}
+ streams := new(libpod.AttachStreams)
+ streams.OutputStream = stdout
+ streams.ErrorStream = stderr
+ streams.InputStream = stdin
+ streams.AttachOutput = true
+ streams.AttachError = true
+ streams.AttachInput = true
+
+ if stdout == nil {
+ logrus.Debugf("Not attaching to stdout")
+ streams.AttachOutput = false
+ }
+ if stderr == nil {
+ logrus.Debugf("Not attaching to stderr")
+ streams.AttachError = false
+ }
+ if stdin == nil {
+ logrus.Debugf("Not attaching to stdin")
+ streams.AttachInput = false
+ }
+
if sigProxy {
ProxySignals(ctr)
}
- return ctr.Attach(stdout, stderr, stdin, detachKeys, resize)
+ return ctr.Attach(streams, detachKeys, resize)
}
// Start and attach to a container
@@ -119,7 +140,28 @@ func startAttachCtr(ctr *libpod.Container, stdout, stderr, stdin *os.File, detac
defer term.RestoreTerminal(os.Stdin.Fd(), oldTermState)
}
- attachChan, err := ctr.StartAndAttach(stdout, stderr, stdin, detachKeys, resize)
+ streams := new(libpod.AttachStreams)
+ streams.OutputStream = stdout
+ streams.ErrorStream = stderr
+ streams.InputStream = stdin
+ streams.AttachOutput = true
+ streams.AttachError = true
+ streams.AttachInput = true
+
+ if stdout == nil {
+ logrus.Debugf("Not attaching to stdout")
+ streams.AttachOutput = false
+ }
+ if stderr == nil {
+ logrus.Debugf("Not attaching to stderr")
+ streams.AttachError = false
+ }
+ if stdin == nil {
+ logrus.Debugf("Not attaching to stdin")
+ streams.AttachInput = false
+ }
+
+ attachChan, err := ctr.StartAndAttach(streams, detachKeys, resize)
if err != nil {
return err
}
diff --git a/libpod/container_api.go b/libpod/container_api.go
index fb6c70fd0..2d5c2bef3 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -1,7 +1,6 @@
package libpod
import (
- "io"
"io/ioutil"
"os"
"strconv"
@@ -125,7 +124,7 @@ func (c *Container) Start() (err error) {
// attach call.
// The channel will be closed automatically after the result of attach has been
// sent
-func (c *Container) StartAndAttach(outputStream, errorStream io.WriteCloser, inputStream io.Reader, keys string, resize <-chan remotecommand.TerminalSize) (attachResChan <-chan error, err error) {
+func (c *Container) StartAndAttach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize) (attachResChan <-chan error, err error) {
if !c.locked {
c.lock.Lock()
defer c.lock.Unlock()
@@ -178,7 +177,7 @@ func (c *Container) StartAndAttach(outputStream, errorStream io.WriteCloser, inp
// Attach to the container before starting it
go func() {
- if err := c.attach(outputStream, errorStream, inputStream, keys, resize); err != nil {
+ if err := c.attach(streams, keys, resize); err != nil {
attachChan <- err
}
close(attachChan)
@@ -406,7 +405,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e
}
// Attach attaches to a container
-func (c *Container) Attach(outputStream, errorStream io.WriteCloser, inputStream io.Reader, keys string, resize <-chan remotecommand.TerminalSize) error {
+func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize) error {
if !c.locked {
c.lock.Lock()
if err := c.syncContainer(); err != nil {
@@ -421,7 +420,7 @@ func (c *Container) Attach(outputStream, errorStream io.WriteCloser, inputStream
return errors.Wrapf(ErrCtrStateInvalid, "can only attach to created or running containers")
}
- return c.attach(outputStream, errorStream, inputStream, keys, resize)
+ return c.attach(streams, keys, resize)
}
// Mount mounts a container's filesystem on the host
diff --git a/libpod/container_attach.go b/libpod/container_attach.go
index 2e65755d9..8b0aaed06 100644
--- a/libpod/container_attach.go
+++ b/libpod/container_attach.go
@@ -23,16 +23,35 @@ const (
AttachPipeStderr = 3
)
+// 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 io.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 to the given container
// Does not check if state is appropriate
-func (c *Container) attach(outputStream, errorStream io.WriteCloser, inputStream io.Reader, keys string, resize <-chan remotecommand.TerminalSize) error {
- if outputStream == nil && errorStream == nil && inputStream == nil {
+func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize) error {
+ if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
return errors.Wrapf(ErrInvalidArg, "must provide at least one stream to attach to")
}
// Do not allow stdin on containers without Stdin set
// Conmon was not configured properly
- if inputStream != nil && !c.config.Stdin {
+ if streams.AttachInput && !c.config.Stdin {
return errors.Wrapf(ErrInvalidArg, "this container was not created as interactive, cannot attach stdin")
}
@@ -48,12 +67,12 @@ func (c *Container) attach(outputStream, errorStream io.WriteCloser, inputStream
logrus.Debugf("Attaching to container %s", c.ID())
- return c.attachContainerSocket(resize, detachKeys, outputStream, errorStream, inputStream)
+ return c.attachContainerSocket(resize, detachKeys, streams)
}
// attachContainerSocket connects to the container's attach socket and deals with the IO
// TODO add a channel to allow interruptiong
-func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, outputStream, errorStream io.WriteCloser, inputStream io.Reader) error {
+func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams) error {
kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) {
controlPath := filepath.Join(c.bundlePath(), "ctl")
controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0)
@@ -77,17 +96,17 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi
defer conn.Close()
receiveStdoutError := make(chan error)
- if outputStream != nil || errorStream != nil {
+ if streams.AttachOutput || streams.AttachError {
go func() {
- receiveStdoutError <- redirectResponseToOutputStreams(outputStream, errorStream, conn)
+ receiveStdoutError <- redirectResponseToOutputStreams(streams.OutputStream, streams.ErrorStream, conn)
}()
}
stdinDone := make(chan error)
go func() {
var err error
- if inputStream != nil {
- _, err = utils.CopyDetachable(conn, inputStream, detachKeys)
+ if streams.AttachInput {
+ _, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys)
conn.CloseWrite()
}
stdinDone <- err
@@ -100,7 +119,7 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi
if _, ok := err.(utils.DetachError); ok {
return nil
}
- if outputStream != nil || errorStream != nil {
+ if streams.AttachOutput || streams.AttachError {
return <-receiveStdoutError
}
}