mirror of
https://github.com/containers/podman.git
synced 2025-06-07 07:45:34 +08:00

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>
122 lines
3.3 KiB
Go
122 lines
3.3 KiB
Go
package adapter
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/containers/libpod/libpod"
|
|
"github.com/containers/libpod/libpod/define"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/crypto/ssh/terminal"
|
|
"k8s.io/client-go/tools/remotecommand"
|
|
)
|
|
|
|
// ExecAttachCtr execs and attaches to a container
|
|
func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, tty, privileged bool, env map[string]string, cmd []string, user, workDir string, streams *define.AttachStreams, preserveFDs uint, detachKeys string) (int, error) {
|
|
resize := make(chan remotecommand.TerminalSize)
|
|
haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
|
|
|
|
// Check if we are attached to a terminal. If we are, generate resize
|
|
// events, and set the terminal to raw mode
|
|
if haveTerminal && tty {
|
|
cancel, oldTermState, err := handleTerminalAttach(ctx, resize)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
defer cancel()
|
|
defer func() {
|
|
if err := restoreTerminal(oldTermState); err != nil {
|
|
logrus.Errorf("unable to restore terminal: %q", err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
execConfig := new(libpod.ExecConfig)
|
|
execConfig.Command = cmd
|
|
execConfig.Terminal = tty
|
|
execConfig.Privileged = privileged
|
|
execConfig.Environment = env
|
|
execConfig.User = user
|
|
execConfig.WorkDir = workDir
|
|
execConfig.DetachKeys = &detachKeys
|
|
execConfig.PreserveFDs = preserveFDs
|
|
|
|
return ctr.Exec(execConfig, streams, resize)
|
|
}
|
|
|
|
// StartAttachCtr starts and (if required) attaches to a container
|
|
// if you change the signature of this function from os.File to io.Writer, it will trigger a downstream
|
|
// error. we may need to just lint disable this one.
|
|
func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error { //nolint-interfacer
|
|
resize := make(chan remotecommand.TerminalSize)
|
|
|
|
haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
|
|
|
|
// Check if we are attached to a terminal. If we are, generate resize
|
|
// events, and set the terminal to raw mode
|
|
if haveTerminal && ctr.Spec().Process.Terminal {
|
|
cancel, oldTermState, err := handleTerminalAttach(ctx, resize)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
if err := restoreTerminal(oldTermState); err != nil {
|
|
logrus.Errorf("unable to restore terminal: %q", err)
|
|
}
|
|
}()
|
|
defer cancel()
|
|
}
|
|
|
|
streams := new(define.AttachStreams)
|
|
streams.OutputStream = stdout
|
|
streams.ErrorStream = stderr
|
|
streams.InputStream = bufio.NewReader(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 !startContainer {
|
|
if sigProxy {
|
|
ProxySignals(ctr)
|
|
}
|
|
|
|
return ctr.Attach(streams, detachKeys, resize)
|
|
}
|
|
|
|
attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if sigProxy {
|
|
ProxySignals(ctr)
|
|
}
|
|
|
|
if stdout == nil && stderr == nil {
|
|
fmt.Printf("%s\n", ctr.ID())
|
|
}
|
|
|
|
err = <-attachChan
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
|
|
}
|
|
|
|
return nil
|
|
}
|