mirror of https://github.com/docker/docs.git
Move current tty and pipe impl to lxc driver
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
8e2284aaa2
commit
aac702727e
|
@ -1133,9 +1133,9 @@ func (container *Container) Exposes(p nat.Port) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) GetPtyMaster() (*os.File, error) {
|
func (container *Container) GetPtyMaster() (*os.File, error) {
|
||||||
ttyConsole, ok := container.command.Terminal.(*execdriver.TtyConsole)
|
ttyConsole, ok := container.command.Terminal.(execdriver.TtyTerminal)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrNoTTY
|
return nil, ErrNoTTY
|
||||||
}
|
}
|
||||||
return ttyConsole.Master, nil
|
return ttyConsole.Master(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package execdriver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,6 +59,18 @@ type Info interface {
|
||||||
IsRunning() bool
|
IsRunning() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Terminal in an interface for drivers to implement
|
||||||
|
// if they want to support Close and Resize calls from
|
||||||
|
// the core
|
||||||
|
type Terminal interface {
|
||||||
|
io.Closer
|
||||||
|
Resize(height, width int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type TtyTerminal interface {
|
||||||
|
Master() *os.File
|
||||||
|
}
|
||||||
|
|
||||||
type Driver interface {
|
type Driver interface {
|
||||||
Run(c *Command, pipes *Pipes, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code
|
Run(c *Command, pipes *Pipes, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code
|
||||||
Kill(c *Command, sig int) error
|
Kill(c *Command, sig int) error
|
||||||
|
@ -99,8 +113,8 @@ type Command struct {
|
||||||
Config []string `json:"config"` // generic values that specific drivers can consume
|
Config []string `json:"config"` // generic values that specific drivers can consume
|
||||||
Resources *Resources `json:"resources"`
|
Resources *Resources `json:"resources"`
|
||||||
|
|
||||||
Terminal Term `json:"-"`
|
Terminal Terminal `json:"-"` // standard or tty terminal
|
||||||
Console string `json:"-"`
|
Console string `json:"-"` // dev/console path
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the pid of the process
|
// Return the pid of the process
|
||||||
|
|
|
@ -77,7 +77,7 @@ func (d *driver) Name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
||||||
if err := execdriver.SetTerminal(c, pipes); err != nil {
|
if err := SetTerminal(c, pipes); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
configPath, err := d.generateLXCConfig(c)
|
configPath, err := d.generateLXCConfig(c)
|
||||||
|
|
|
@ -1,36 +1,16 @@
|
||||||
package execdriver
|
package lxc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/dotcloud/docker/execdriver"
|
||||||
"github.com/dotcloud/docker/pkg/term"
|
"github.com/dotcloud/docker/pkg/term"
|
||||||
"github.com/kr/pty"
|
"github.com/kr/pty"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Term interface {
|
func SetTerminal(command *execdriver.Command, pipes *execdriver.Pipes) error {
|
||||||
io.Closer
|
|
||||||
Resize(height, width int) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type Pipes struct {
|
|
||||||
Stdin io.ReadCloser
|
|
||||||
Stdout, Stderr io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPipes(stdin io.ReadCloser, stdout, stderr io.Writer, useStdin bool) *Pipes {
|
|
||||||
p := &Pipes{
|
|
||||||
Stdout: stdout,
|
|
||||||
Stderr: stderr,
|
|
||||||
}
|
|
||||||
if useStdin {
|
|
||||||
p.Stdin = stdin
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetTerminal(command *Command, pipes *Pipes) error {
|
|
||||||
var (
|
var (
|
||||||
term Term
|
term execdriver.Terminal
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if command.Tty {
|
if command.Tty {
|
||||||
|
@ -46,18 +26,18 @@ func SetTerminal(command *Command, pipes *Pipes) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TtyConsole struct {
|
type TtyConsole struct {
|
||||||
Master *os.File
|
master *os.File
|
||||||
Slave *os.File
|
slave *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTtyConsole(command *Command, pipes *Pipes) (*TtyConsole, error) {
|
func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
||||||
ptyMaster, ptySlave, err := pty.Open()
|
ptyMaster, ptySlave, err := pty.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tty := &TtyConsole{
|
tty := &TtyConsole{
|
||||||
Master: ptyMaster,
|
master: ptyMaster,
|
||||||
Slave: ptySlave,
|
slave: ptySlave,
|
||||||
}
|
}
|
||||||
if err := tty.attach(command, pipes); err != nil {
|
if err := tty.attach(command, pipes); err != nil {
|
||||||
tty.Close()
|
tty.Close()
|
||||||
|
@ -66,14 +46,18 @@ func NewTtyConsole(command *Command, pipes *Pipes) (*TtyConsole, error) {
|
||||||
return tty, nil
|
return tty, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TtyConsole) Resize(h, w int) error {
|
func (t *TtyConsole) Master() *os.File {
|
||||||
return term.SetWinsize(t.Master.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
|
return t.master
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TtyConsole) attach(command *Command, pipes *Pipes) error {
|
func (t *TtyConsole) Resize(h, w int) error {
|
||||||
command.Stdout = t.Slave
|
return term.SetWinsize(t.master.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
|
||||||
command.Stderr = t.Slave
|
}
|
||||||
command.Console = t.Slave.Name()
|
|
||||||
|
func (t *TtyConsole) attach(command *execdriver.Command, pipes *execdriver.Pipes) error {
|
||||||
|
command.Stdout = t.slave
|
||||||
|
command.Stderr = t.slave
|
||||||
|
command.Console = t.slave.Name()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if wb, ok := pipes.Stdout.(interface {
|
if wb, ok := pipes.Stdout.(interface {
|
||||||
|
@ -81,30 +65,30 @@ func (t *TtyConsole) attach(command *Command, pipes *Pipes) error {
|
||||||
}); ok {
|
}); ok {
|
||||||
defer wb.CloseWriters()
|
defer wb.CloseWriters()
|
||||||
}
|
}
|
||||||
io.Copy(pipes.Stdout, t.Master)
|
io.Copy(pipes.Stdout, t.master)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if pipes.Stdin != nil {
|
if pipes.Stdin != nil {
|
||||||
command.Stdin = t.Slave
|
command.Stdin = t.slave
|
||||||
command.SysProcAttr.Setctty = true
|
command.SysProcAttr.Setctty = true
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer pipes.Stdin.Close()
|
defer pipes.Stdin.Close()
|
||||||
io.Copy(t.Master, pipes.Stdin)
|
io.Copy(t.master, pipes.Stdin)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TtyConsole) Close() error {
|
func (t *TtyConsole) Close() error {
|
||||||
t.Slave.Close()
|
t.slave.Close()
|
||||||
return t.Master.Close()
|
return t.master.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
type StdConsole struct {
|
type StdConsole struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStdConsole(command *Command, pipes *Pipes) (*StdConsole, error) {
|
func NewStdConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*StdConsole, error) {
|
||||||
std := &StdConsole{}
|
std := &StdConsole{}
|
||||||
|
|
||||||
if err := std.attach(command, pipes); err != nil {
|
if err := std.attach(command, pipes); err != nil {
|
||||||
|
@ -113,7 +97,7 @@ func NewStdConsole(command *Command, pipes *Pipes) (*StdConsole, error) {
|
||||||
return std, nil
|
return std, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StdConsole) attach(command *Command, pipes *Pipes) error {
|
func (s *StdConsole) attach(command *execdriver.Command, pipes *execdriver.Pipes) error {
|
||||||
command.Stdout = pipes.Stdout
|
command.Stdout = pipes.Stdout
|
||||||
command.Stderr = pipes.Stderr
|
command.Stderr = pipes.Stderr
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package execdriver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pipes is a wrapper around a containers output for
|
||||||
|
// stdin, stdout, stderr
|
||||||
|
type Pipes struct {
|
||||||
|
Stdin io.ReadCloser
|
||||||
|
Stdout, Stderr io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPipes(stdin io.ReadCloser, stdout, stderr io.Writer, useStdin bool) *Pipes {
|
||||||
|
p := &Pipes{
|
||||||
|
Stdout: stdout,
|
||||||
|
Stderr: stderr,
|
||||||
|
}
|
||||||
|
if useStdin {
|
||||||
|
p.Stdin = stdin
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
Loading…
Reference in New Issue