mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 02:15:43 +03:00
executors: implement streaming exec
Implements streamign exec handling in both executors (i.e. universal and libcontainer). For creation of TTY, some incidental complexity leaked in. The universal executor uses github.com/kr/pty for creation of TTYs. On the other hand, libcontainer expects a console socket and for libcontainer to create the underlying console object on process start. The caller can then use `libcontainer.utils.RecvFd()` to get tty master end. I chose github.com/kr/pty for managing TTYs here. I tried `github.com/containerd/console` package (which is already imported), but the package did not work as expected on macOS.
This commit is contained in:
@@ -5,6 +5,7 @@ package executor
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
@@ -28,6 +29,7 @@ import (
|
||||
cgroupFs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
|
||||
lconfigs "github.com/opencontainers/runc/libcontainer/configs"
|
||||
ldevices "github.com/opencontainers/runc/libcontainer/devices"
|
||||
lutils "github.com/opencontainers/runc/libcontainer/utils"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
@@ -504,6 +506,53 @@ func (l *LibcontainerExecutor) Exec(deadline time.Time, cmd string, args []strin
|
||||
|
||||
}
|
||||
|
||||
func (l *LibcontainerExecutor) newTerminalSocket() (master func() (*os.File, error), socket *os.File, err error) {
|
||||
parent, child, err := lutils.NewSockPair("socket")
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create terminal: %v", err)
|
||||
}
|
||||
|
||||
return func() (*os.File, error) { return lutils.RecvFd(parent) }, child, err
|
||||
|
||||
}
|
||||
|
||||
func (l *LibcontainerExecutor) ExecStreaming(ctx context.Context, cmd []string, tty bool,
|
||||
stream drivers.ExecTaskStream) error {
|
||||
|
||||
// the task process will be started by the container
|
||||
process := &libcontainer.Process{
|
||||
Args: cmd,
|
||||
Env: l.userProc.Env,
|
||||
User: l.userProc.User,
|
||||
Init: false,
|
||||
Cwd: "/",
|
||||
}
|
||||
|
||||
execHelper := &execHelper{
|
||||
logger: l.logger,
|
||||
|
||||
newTerminal: l.newTerminalSocket,
|
||||
setTTY: func(tty *os.File) error {
|
||||
process.ConsoleSocket = tty
|
||||
return nil
|
||||
},
|
||||
setIO: func(stdin io.Reader, stdout, stderr io.Writer) error {
|
||||
process.Stdin = stdin
|
||||
process.Stdout = stdout
|
||||
process.Stderr = stderr
|
||||
return nil
|
||||
},
|
||||
|
||||
processStart: func() error { return l.container.Run(process) },
|
||||
processWait: func() (*os.ProcessState, error) {
|
||||
return process.Wait()
|
||||
},
|
||||
}
|
||||
|
||||
return execHelper.run(ctx, tty, stream)
|
||||
|
||||
}
|
||||
|
||||
type waitResult struct {
|
||||
ps *os.ProcessState
|
||||
err error
|
||||
|
||||
Reference in New Issue
Block a user