diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2018-04-12 12:26:51 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-04-13 18:43:44 +0000 |
commit | 8d7635b1ac3eaea83fcf481994294eb137110e96 (patch) | |
tree | 9b78bbbeb9b33005c2f29b4fc248d3e7b2ddbf16 | |
parent | 6609d555f75568bb4f1394736a3e3b31e5f0d355 (diff) | |
download | podman-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.go | 48 | ||||
-rw-r--r-- | libpod/container_api.go | 9 | ||||
-rw-r--r-- | libpod/container_attach.go | 39 |
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 } } |