mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Refactoring execdriver.Command and Container structs to support 'docker exec' and other
similar features in the future. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan <vishnuk@google.com> (github: vishh)
This commit is contained in:
parent
9ffb0f76f2
commit
4aa5da278f
15 changed files with 150 additions and 134 deletions
|
@ -103,7 +103,6 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
|
||||||
}
|
}
|
||||||
|
|
||||||
<-daemon.Attach(container, cStdin, cStdinCloser, cStdout, cStderr)
|
<-daemon.Attach(container, cStdin, cStdinCloser, cStdout, cStderr)
|
||||||
|
|
||||||
// If we are in stdinonce mode, wait for the process to end
|
// If we are in stdinonce mode, wait for the process to end
|
||||||
// otherwise, simply return
|
// otherwise, simply return
|
||||||
if container.Config.StdinOnce && !container.Config.Tty {
|
if container.Config.StdinOnce && !container.Config.Tty {
|
||||||
|
@ -128,7 +127,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
|
||||||
|
|
||||||
if stdin != nil && container.Config.OpenStdin {
|
if stdin != nil && container.Config.OpenStdin {
|
||||||
nJobs++
|
nJobs++
|
||||||
if cStdin, err := container.StdinPipe(); err != nil {
|
if cStdin, err := container.StdConfig.StdinPipe(); err != nil {
|
||||||
errors <- err
|
errors <- err
|
||||||
} else {
|
} else {
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -164,7 +163,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
|
||||||
}
|
}
|
||||||
if stdout != nil {
|
if stdout != nil {
|
||||||
nJobs++
|
nJobs++
|
||||||
if p, err := container.StdoutPipe(); err != nil {
|
if p, err := container.StdConfig.StdoutPipe(); err != nil {
|
||||||
errors <- err
|
errors <- err
|
||||||
} else {
|
} else {
|
||||||
cStdout = p
|
cStdout = p
|
||||||
|
@ -193,7 +192,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
|
||||||
if stdinCloser != nil {
|
if stdinCloser != nil {
|
||||||
defer stdinCloser.Close()
|
defer stdinCloser.Close()
|
||||||
}
|
}
|
||||||
if cStdout, err := container.StdoutPipe(); err != nil {
|
if cStdout, err := container.StdConfig.StdoutPipe(); err != nil {
|
||||||
log.Errorf("attach: stdout pipe: %s", err)
|
log.Errorf("attach: stdout pipe: %s", err)
|
||||||
} else {
|
} else {
|
||||||
io.Copy(&utils.NopWriter{}, cStdout)
|
io.Copy(&utils.NopWriter{}, cStdout)
|
||||||
|
@ -202,7 +201,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
|
||||||
}
|
}
|
||||||
if stderr != nil {
|
if stderr != nil {
|
||||||
nJobs++
|
nJobs++
|
||||||
if p, err := container.StderrPipe(); err != nil {
|
if p, err := container.StdConfig.StderrPipe(); err != nil {
|
||||||
errors <- err
|
errors <- err
|
||||||
} else {
|
} else {
|
||||||
cStderr = p
|
cStderr = p
|
||||||
|
@ -232,7 +231,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
|
||||||
defer stdinCloser.Close()
|
defer stdinCloser.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if cStderr, err := container.StderrPipe(); err != nil {
|
if cStderr, err := container.StdConfig.StderrPipe(); err != nil {
|
||||||
log.Errorf("attach: stdout pipe: %s", err)
|
log.Errorf("attach: stdout pipe: %s", err)
|
||||||
} else {
|
} else {
|
||||||
io.Copy(&utils.NopWriter{}, cStderr)
|
io.Copy(&utils.NopWriter{}, cStderr)
|
||||||
|
|
|
@ -41,6 +41,13 @@ var (
|
||||||
ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
|
ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type StdConfig struct {
|
||||||
|
stdout *broadcastwriter.BroadcastWriter
|
||||||
|
stderr *broadcastwriter.BroadcastWriter
|
||||||
|
stdin io.ReadCloser
|
||||||
|
stdinPipe io.WriteCloser
|
||||||
|
}
|
||||||
|
|
||||||
type Container struct {
|
type Container struct {
|
||||||
*State
|
*State
|
||||||
root string // Path to the "home" of the container, including metadata.
|
root string // Path to the "home" of the container, including metadata.
|
||||||
|
@ -66,10 +73,7 @@ type Container struct {
|
||||||
ExecDriver string
|
ExecDriver string
|
||||||
|
|
||||||
command *execdriver.Command
|
command *execdriver.Command
|
||||||
stdout *broadcastwriter.BroadcastWriter
|
StdConfig StdConfig
|
||||||
stderr *broadcastwriter.BroadcastWriter
|
|
||||||
stdin io.ReadCloser
|
|
||||||
stdinPipe io.WriteCloser
|
|
||||||
|
|
||||||
daemon *Daemon
|
daemon *Daemon
|
||||||
MountLabel, ProcessLabel string
|
MountLabel, ProcessLabel string
|
||||||
|
@ -247,26 +251,31 @@ func populateCommand(c *Container, env []string) error {
|
||||||
CpuShares: c.Config.CpuShares,
|
CpuShares: c.Config.CpuShares,
|
||||||
Cpuset: c.Config.Cpuset,
|
Cpuset: c.Config.Cpuset,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processConfig := execdriver.ProcessConfig{
|
||||||
|
Privileged: c.hostConfig.Privileged,
|
||||||
|
Entrypoint: c.Path,
|
||||||
|
Arguments: c.Args,
|
||||||
|
Tty: c.Config.Tty,
|
||||||
|
User: c.Config.User,
|
||||||
|
}
|
||||||
|
processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||||
|
processConfig.Env = env
|
||||||
c.command = &execdriver.Command{
|
c.command = &execdriver.Command{
|
||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
Privileged: c.hostConfig.Privileged,
|
|
||||||
Rootfs: c.RootfsPath(),
|
Rootfs: c.RootfsPath(),
|
||||||
InitPath: "/.dockerinit",
|
InitPath: "/.dockerinit",
|
||||||
Entrypoint: c.Path,
|
|
||||||
Arguments: c.Args,
|
|
||||||
WorkingDir: c.Config.WorkingDir,
|
WorkingDir: c.Config.WorkingDir,
|
||||||
Network: en,
|
Network: en,
|
||||||
Tty: c.Config.Tty,
|
|
||||||
User: c.Config.User,
|
|
||||||
Config: context,
|
Config: context,
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
AllowedDevices: allowedDevices,
|
AllowedDevices: allowedDevices,
|
||||||
AutoCreatedDevices: autoCreatedDevices,
|
AutoCreatedDevices: autoCreatedDevices,
|
||||||
CapAdd: c.hostConfig.CapAdd,
|
CapAdd: c.hostConfig.CapAdd,
|
||||||
CapDrop: c.hostConfig.CapDrop,
|
CapDrop: c.hostConfig.CapDrop,
|
||||||
|
ProcessConfig: processConfig,
|
||||||
}
|
}
|
||||||
c.command.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
|
||||||
c.command.Env = env
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +338,7 @@ func (container *Container) Run() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) Output() (output []byte, err error) {
|
func (container *Container) Output() (output []byte, err error) {
|
||||||
pipe, err := container.StdoutPipe()
|
pipe, err := container.StdConfig.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -342,7 +351,7 @@ func (container *Container) Output() (output []byte, err error) {
|
||||||
return output, err
|
return output, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container.StdinPipe returns a WriteCloser which can be used to feed data
|
// StdConfig.StdinPipe returns a WriteCloser which can be used to feed data
|
||||||
// to the standard input of the container's active process.
|
// to the standard input of the container's active process.
|
||||||
// Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
|
// Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
|
||||||
// which can be used to retrieve the standard output (and error) generated
|
// which can be used to retrieve the standard output (and error) generated
|
||||||
|
@ -350,31 +359,31 @@ func (container *Container) Output() (output []byte, err error) {
|
||||||
// copied and delivered to all StdoutPipe and StderrPipe consumers, using
|
// copied and delivered to all StdoutPipe and StderrPipe consumers, using
|
||||||
// a kind of "broadcaster".
|
// a kind of "broadcaster".
|
||||||
|
|
||||||
func (container *Container) StdinPipe() (io.WriteCloser, error) {
|
func (stdConfig *StdConfig) StdinPipe() (io.WriteCloser, error) {
|
||||||
return container.stdinPipe, nil
|
return stdConfig.stdinPipe, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) StdoutPipe() (io.ReadCloser, error) {
|
func (stdConfig *StdConfig) StdoutPipe() (io.ReadCloser, error) {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
container.stdout.AddWriter(writer, "")
|
stdConfig.stdout.AddWriter(writer, "")
|
||||||
return utils.NewBufReader(reader), nil
|
return utils.NewBufReader(reader), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) StderrPipe() (io.ReadCloser, error) {
|
func (stdConfig *StdConfig) StderrPipe() (io.ReadCloser, error) {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
container.stderr.AddWriter(writer, "")
|
stdConfig.stderr.AddWriter(writer, "")
|
||||||
return utils.NewBufReader(reader), nil
|
return utils.NewBufReader(reader), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) StdoutLogPipe() io.ReadCloser {
|
func (container *Container) StdoutLogPipe() io.ReadCloser {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
container.stdout.AddWriter(writer, "stdout")
|
container.StdConfig.stdout.AddWriter(writer, "stdout")
|
||||||
return utils.NewBufReader(reader)
|
return utils.NewBufReader(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) StderrLogPipe() io.ReadCloser {
|
func (container *Container) StderrLogPipe() io.ReadCloser {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
container.stderr.AddWriter(writer, "stderr")
|
container.StdConfig.stderr.AddWriter(writer, "stderr")
|
||||||
return utils.NewBufReader(reader)
|
return utils.NewBufReader(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,7 +640,7 @@ func (container *Container) Restart(seconds int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) Resize(h, w int) error {
|
func (container *Container) Resize(h, w int) error {
|
||||||
return container.command.Terminal.Resize(h, w)
|
return container.command.ProcessConfig.Terminal.Resize(h, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) ExportRw() (archive.Archive, error) {
|
func (container *Container) ExportRw() (archive.Archive, error) {
|
||||||
|
@ -815,7 +824,7 @@ 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.TtyTerminal)
|
ttyConsole, ok := container.command.ProcessConfig.Terminal.(execdriver.TtyTerminal)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrNoTTY
|
return nil, ErrNoTTY
|
||||||
}
|
}
|
||||||
|
@ -1083,11 +1092,11 @@ func (container *Container) startLoggingToDisk() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.daemon.LogToDisk(container.stdout, pth, "stdout"); err != nil {
|
if err := container.daemon.LogToDisk(container.StdConfig.stdout, pth, "stdout"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.daemon.LogToDisk(container.stderr, pth, "stderr"); err != nil {
|
if err := container.daemon.LogToDisk(container.StdConfig.stderr, pth, "stderr"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,13 +195,13 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err
|
||||||
container.daemon = daemon
|
container.daemon = daemon
|
||||||
|
|
||||||
// Attach to stdout and stderr
|
// Attach to stdout and stderr
|
||||||
container.stderr = broadcastwriter.New()
|
container.StdConfig.stderr = broadcastwriter.New()
|
||||||
container.stdout = broadcastwriter.New()
|
container.StdConfig.stdout = broadcastwriter.New()
|
||||||
// Attach to stdin
|
// Attach to stdin
|
||||||
if container.Config.OpenStdin {
|
if container.Config.OpenStdin {
|
||||||
container.stdin, container.stdinPipe = io.Pipe()
|
container.StdConfig.stdin, container.StdConfig.stdinPipe = io.Pipe()
|
||||||
} else {
|
} else {
|
||||||
container.stdinPipe = utils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
|
container.StdConfig.stdinPipe = utils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
|
||||||
}
|
}
|
||||||
// done
|
// done
|
||||||
daemon.containers.Add(container.ID, container)
|
daemon.containers.Add(container.ID, container)
|
||||||
|
@ -229,7 +229,7 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err
|
||||||
ID: container.ID,
|
ID: container.ID,
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
cmd.Process, err = os.FindProcess(existingPid)
|
cmd.ProcessConfig.Process, err = os.FindProcess(existingPid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("cannot find existing process for %d", existingPid)
|
log.Debugf("cannot find existing process for %d", existingPid)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ var (
|
||||||
ErrDriverNotFound = errors.New("The requested docker init has not been found")
|
ErrDriverNotFound = errors.New("The requested docker init has not been found")
|
||||||
)
|
)
|
||||||
|
|
||||||
type StartCallback func(*Command)
|
type StartCallback func(*ProcessConfig)
|
||||||
|
|
||||||
// Driver specific information based on
|
// Driver specific information based on
|
||||||
// processes registered with the driver
|
// processes registered with the driver
|
||||||
|
@ -80,20 +80,27 @@ type Mount struct {
|
||||||
Private bool `json:"private"`
|
Private bool `json:"private"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process wrapps an os/exec.Cmd to add more metadata
|
// Describes a process that will be run inside a container.
|
||||||
type Command struct {
|
type ProcessConfig struct {
|
||||||
exec.Cmd `json:"-"`
|
exec.Cmd `json:"-"`
|
||||||
|
|
||||||
|
Privileged bool `json:"privileged"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Tty bool `json:"tty"`
|
||||||
|
Entrypoint string `json:"entrypoint"`
|
||||||
|
Arguments []string `json:"arguments"`
|
||||||
|
Terminal Terminal `json:"-"` // standard or tty terminal
|
||||||
|
ContainerPid int `json:"container_pid"` // the pid for the process inside a container
|
||||||
|
Console string `json:"-"` // dev/console path
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process wrapps an os/exec.Cmd to add more metadata
|
||||||
|
type Command struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Privileged bool `json:"privileged"`
|
|
||||||
User string `json:"user"`
|
|
||||||
Rootfs string `json:"rootfs"` // root fs of the container
|
Rootfs string `json:"rootfs"` // root fs of the container
|
||||||
InitPath string `json:"initpath"` // dockerinit
|
InitPath string `json:"initpath"` // dockerinit
|
||||||
Entrypoint string `json:"entrypoint"`
|
|
||||||
Arguments []string `json:"arguments"`
|
|
||||||
WorkingDir string `json:"working_dir"`
|
WorkingDir string `json:"working_dir"`
|
||||||
ConfigPath string `json:"config_path"` // this should be able to be removed when the lxc template is moved into the driver
|
ConfigPath string `json:"config_path"` // this should be able to be removed when the lxc template is moved into the driver
|
||||||
Tty bool `json:"tty"`
|
|
||||||
Network *Network `json:"network"`
|
Network *Network `json:"network"`
|
||||||
Config map[string][]string `json:"config"` // generic values that specific drivers can consume
|
Config map[string][]string `json:"config"` // generic values that specific drivers can consume
|
||||||
Resources *Resources `json:"resources"`
|
Resources *Resources `json:"resources"`
|
||||||
|
@ -103,13 +110,11 @@ type Command struct {
|
||||||
CapAdd []string `json:"cap_add"`
|
CapAdd []string `json:"cap_add"`
|
||||||
CapDrop []string `json:"cap_drop"`
|
CapDrop []string `json:"cap_drop"`
|
||||||
|
|
||||||
Terminal Terminal `json:"-"` // standard or tty terminal
|
ProcessConfig ProcessConfig `json:"process_config"` // Describes the init process of the container.
|
||||||
Console string `json:"-"` // dev/console path
|
|
||||||
ContainerPid int `json:"container_pid"` // the pid for the process inside a container
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the pid of the process
|
// Return the pid of the process
|
||||||
// If the process is nil -1 will be returned
|
// If the process is nil -1 will be returned
|
||||||
func (c *Command) Pid() int {
|
func (processConfig *ProcessConfig) Pid() int {
|
||||||
return c.ContainerPid
|
return processConfig.ContainerPid
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,12 +59,12 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Tty {
|
if c.ProcessConfig.Tty {
|
||||||
term, err = NewTtyConsole(c, pipes)
|
term, err = NewTtyConsole(&c.ProcessConfig, pipes)
|
||||||
} else {
|
} else {
|
||||||
term, err = execdriver.NewStdConsole(c, pipes)
|
term, err = execdriver.NewStdConsole(&c.ProcessConfig, pipes)
|
||||||
}
|
}
|
||||||
c.Terminal = term
|
c.ProcessConfig.Terminal = term
|
||||||
|
|
||||||
c.Mounts = append(c.Mounts, execdriver.Mount{
|
c.Mounts = append(c.Mounts, execdriver.Mount{
|
||||||
Source: d.initPath,
|
Source: d.initPath,
|
||||||
|
@ -98,11 +98,11 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
"-mtu", strconv.Itoa(c.Network.Mtu),
|
"-mtu", strconv.Itoa(c.Network.Mtu),
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.User != "" {
|
if c.ProcessConfig.User != "" {
|
||||||
params = append(params, "-u", c.User)
|
params = append(params, "-u", c.ProcessConfig.User)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Privileged {
|
if c.ProcessConfig.Privileged {
|
||||||
if d.apparmor {
|
if d.apparmor {
|
||||||
params[0] = path.Join(d.root, "lxc-start-unconfined")
|
params[0] = path.Join(d.root, "lxc-start-unconfined")
|
||||||
|
|
||||||
|
@ -122,8 +122,8 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
params = append(params, fmt.Sprintf("-cap-drop=%s", strings.Join(c.CapDrop, ":")))
|
params = append(params, fmt.Sprintf("-cap-drop=%s", strings.Join(c.CapDrop, ":")))
|
||||||
}
|
}
|
||||||
|
|
||||||
params = append(params, "--", c.Entrypoint)
|
params = append(params, "--", c.ProcessConfig.Entrypoint)
|
||||||
params = append(params, c.Arguments...)
|
params = append(params, c.ProcessConfig.Arguments...)
|
||||||
|
|
||||||
if d.sharedRoot {
|
if d.sharedRoot {
|
||||||
// lxc-start really needs / to be non-shared, or all kinds of stuff break
|
// lxc-start really needs / to be non-shared, or all kinds of stuff break
|
||||||
|
@ -149,14 +149,14 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
if err != nil {
|
if err != nil {
|
||||||
aname = name
|
aname = name
|
||||||
}
|
}
|
||||||
c.Path = aname
|
c.ProcessConfig.Path = aname
|
||||||
c.Args = append([]string{name}, arg...)
|
c.ProcessConfig.Args = append([]string{name}, arg...)
|
||||||
|
|
||||||
if err := nodes.CreateDeviceNodes(c.Rootfs, c.AutoCreatedDevices); err != nil {
|
if err := nodes.CreateDeviceNodes(c.Rootfs, c.AutoCreatedDevices); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Start(); err != nil {
|
if err := c.ProcessConfig.Start(); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
)
|
)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := c.Wait(); err != nil {
|
if err := c.ProcessConfig.Wait(); err != nil {
|
||||||
if _, ok := err.(*exec.ExitError); !ok { // Do not propagate the error if it's simply a status code != 0
|
if _, ok := err.(*exec.ExitError); !ok { // Do not propagate the error if it's simply a status code != 0
|
||||||
waitErr = err
|
waitErr = err
|
||||||
}
|
}
|
||||||
|
@ -177,17 +177,17 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
// Poll lxc for RUNNING status
|
// Poll lxc for RUNNING status
|
||||||
pid, err := d.waitForStart(c, waitLock)
|
pid, err := d.waitForStart(c, waitLock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c.Process != nil {
|
if c.ProcessConfig.Process != nil {
|
||||||
c.Process.Kill()
|
c.ProcessConfig.Process.Kill()
|
||||||
c.Wait()
|
c.ProcessConfig.Wait()
|
||||||
}
|
}
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ContainerPid = pid
|
c.ProcessConfig.ContainerPid = pid
|
||||||
|
|
||||||
if startCallback != nil {
|
if startCallback != nil {
|
||||||
startCallback(c)
|
startCallback(&c.ProcessConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
<-waitLock
|
<-waitLock
|
||||||
|
@ -198,10 +198,10 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
/// Return the exit code of the process
|
/// Return the exit code of the process
|
||||||
// if the process has not exited -1 will be returned
|
// if the process has not exited -1 will be returned
|
||||||
func getExitCode(c *execdriver.Command) int {
|
func getExitCode(c *execdriver.Command) int {
|
||||||
if c.ProcessState == nil {
|
if c.ProcessConfig.ProcessState == nil {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return c.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
return c.ProcessConfig.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) Kill(c *execdriver.Command, sig int) error {
|
func (d *driver) Kill(c *execdriver.Command, sig int) error {
|
||||||
|
@ -442,7 +442,7 @@ func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) generateEnvConfig(c *execdriver.Command) error {
|
func (d *driver) generateEnvConfig(c *execdriver.Command) error {
|
||||||
data, err := json.Marshal(c.Env)
|
data, err := json.Marshal(c.ProcessConfig.Env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ type TtyConsole struct {
|
||||||
SlavePty *os.File
|
SlavePty *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
||||||
// lxc is special in that we cannot create the master outside of the container without
|
// lxc is special in that we cannot create the master outside of the container without
|
||||||
// opening the slave because we have nothing to provide to the cmd. We have to open both then do
|
// opening the slave because we have nothing to provide to the cmd. We have to open both then do
|
||||||
// the crazy setup on command right now instead of passing the console path to lxc and telling it
|
// the crazy setup on command right now instead of passing the console path to lxc and telling it
|
||||||
|
@ -478,12 +478,12 @@ func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyCo
|
||||||
SlavePty: ptySlave,
|
SlavePty: ptySlave,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tty.AttachPipes(&command.Cmd, pipes); err != nil {
|
if err := tty.AttachPipes(&processConfig.Cmd, pipes); err != nil {
|
||||||
tty.Close()
|
tty.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
command.Console = tty.SlavePty.Name()
|
processConfig.Console = tty.SlavePty.Name()
|
||||||
|
|
||||||
return tty, nil
|
return tty, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ lxc.se_context = {{ .ProcessLabel}}
|
||||||
# no controlling tty at all
|
# no controlling tty at all
|
||||||
lxc.tty = 1
|
lxc.tty = 1
|
||||||
|
|
||||||
{{if .Privileged}}
|
{{if .ProcessConfig.Privileged}}
|
||||||
lxc.cgroup.devices.allow = a
|
lxc.cgroup.devices.allow = a
|
||||||
{{else}}
|
{{else}}
|
||||||
# no implicit access to devices
|
# no implicit access to devices
|
||||||
|
@ -66,7 +66,7 @@ lxc.pivotdir = lxc_putold
|
||||||
lxc.mount.entry = proc {{escapeFstabSpaces $ROOTFS}}/proc proc nosuid,nodev,noexec 0 0
|
lxc.mount.entry = proc {{escapeFstabSpaces $ROOTFS}}/proc proc nosuid,nodev,noexec 0 0
|
||||||
lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noexec 0 0
|
lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noexec 0 0
|
||||||
|
|
||||||
{{if .Tty}}
|
{{if .ProcessConfig.Tty}}
|
||||||
lxc.mount.entry = {{.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw 0 0
|
lxc.mount.entry = {{.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw 0 0
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if .Privileged}}
|
{{if .ProcessConfig.Privileged}}
|
||||||
{{if .AppArmor}}
|
{{if .AppArmor}}
|
||||||
lxc.aa_profile = unconfined
|
lxc.aa_profile = unconfined
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -77,9 +77,11 @@ func TestCustomLxcConfig(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
command := &execdriver.Command{
|
processConfig := execdriver.ProcessConfig{
|
||||||
ID: "1",
|
|
||||||
Privileged: false,
|
Privileged: false,
|
||||||
|
}
|
||||||
|
command := &execdriver.Command{
|
||||||
|
ID: "1",
|
||||||
Config: map[string][]string{
|
Config: map[string][]string{
|
||||||
"lxc": {
|
"lxc": {
|
||||||
"lxc.utsname = docker",
|
"lxc.utsname = docker",
|
||||||
|
@ -90,6 +92,7 @@ func TestCustomLxcConfig(t *testing.T) {
|
||||||
Mtu: 1500,
|
Mtu: 1500,
|
||||||
Interface: nil,
|
Interface: nil,
|
||||||
},
|
},
|
||||||
|
ProcessConfig: processConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := driver.generateLXCConfig(command)
|
p, err := driver.generateLXCConfig(command)
|
||||||
|
|
|
@ -23,11 +23,11 @@ import (
|
||||||
func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, error) {
|
func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, error) {
|
||||||
container := template.New()
|
container := template.New()
|
||||||
|
|
||||||
container.Hostname = getEnv("HOSTNAME", c.Env)
|
container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
|
||||||
container.Tty = c.Tty
|
container.Tty = c.ProcessConfig.Tty
|
||||||
container.User = c.User
|
container.User = c.ProcessConfig.User
|
||||||
container.WorkingDir = c.WorkingDir
|
container.WorkingDir = c.WorkingDir
|
||||||
container.Env = c.Env
|
container.Env = c.ProcessConfig.Env
|
||||||
container.Cgroups.Name = c.ID
|
container.Cgroups.Name = c.ID
|
||||||
container.Cgroups.AllowedDevices = c.AllowedDevices
|
container.Cgroups.AllowedDevices = c.AllowedDevices
|
||||||
container.MountConfig.DeviceNodes = c.AutoCreatedDevices
|
container.MountConfig.DeviceNodes = c.AutoCreatedDevices
|
||||||
|
@ -40,7 +40,7 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, e
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Privileged {
|
if c.ProcessConfig.Privileged {
|
||||||
if err := d.setPrivileged(container); err != nil {
|
if err := d.setPrivileged(container); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,26 +68,26 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
|
|
||||||
var term execdriver.Terminal
|
var term execdriver.Terminal
|
||||||
|
|
||||||
if c.Tty {
|
if c.ProcessConfig.Tty {
|
||||||
term, err = NewTtyConsole(c, pipes)
|
term, err = NewTtyConsole(&c.ProcessConfig, pipes)
|
||||||
} else {
|
} else {
|
||||||
term, err = execdriver.NewStdConsole(c, pipes)
|
term, err = execdriver.NewStdConsole(&c.ProcessConfig, pipes)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
c.Terminal = term
|
c.ProcessConfig.Terminal = term
|
||||||
|
|
||||||
d.Lock()
|
d.Lock()
|
||||||
d.activeContainers[c.ID] = &activeContainer{
|
d.activeContainers[c.ID] = &activeContainer{
|
||||||
container: container,
|
container: container,
|
||||||
cmd: &c.Cmd,
|
cmd: &c.ProcessConfig.Cmd,
|
||||||
}
|
}
|
||||||
d.Unlock()
|
d.Unlock()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dataPath = filepath.Join(d.root, c.ID)
|
dataPath = filepath.Join(d.root, c.ID)
|
||||||
args = append([]string{c.Entrypoint}, c.Arguments...)
|
args = append([]string{c.ProcessConfig.Entrypoint}, c.ProcessConfig.Arguments...)
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := d.createContainerRoot(c.ID); err != nil {
|
if err := d.createContainerRoot(c.ID); err != nil {
|
||||||
|
@ -99,9 +99,9 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespaces.Exec(container, c.Stdin, c.Stdout, c.Stderr, c.Console, c.Rootfs, dataPath, args, func(container *libcontainer.Config, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
|
return namespaces.Exec(container, c.ProcessConfig.Stdin, c.ProcessConfig.Stdout, c.ProcessConfig.Stderr, c.ProcessConfig.Console, c.Rootfs, dataPath, args, func(container *libcontainer.Config, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
|
||||||
c.Path = d.initPath
|
c.ProcessConfig.Path = d.initPath
|
||||||
c.Args = append([]string{
|
c.ProcessConfig.Args = append([]string{
|
||||||
DriverName,
|
DriverName,
|
||||||
"-console", console,
|
"-console", console,
|
||||||
"-pipe", "3",
|
"-pipe", "3",
|
||||||
|
@ -110,25 +110,25 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
}, args...)
|
}, args...)
|
||||||
|
|
||||||
// set this to nil so that when we set the clone flags anything else is reset
|
// set this to nil so that when we set the clone flags anything else is reset
|
||||||
c.SysProcAttr = &syscall.SysProcAttr{
|
c.ProcessConfig.SysProcAttr = &syscall.SysProcAttr{
|
||||||
Cloneflags: uintptr(namespaces.GetNamespaceFlags(container.Namespaces)),
|
Cloneflags: uintptr(namespaces.GetNamespaceFlags(container.Namespaces)),
|
||||||
}
|
}
|
||||||
c.ExtraFiles = []*os.File{child}
|
c.ProcessConfig.ExtraFiles = []*os.File{child}
|
||||||
|
|
||||||
c.Env = container.Env
|
c.ProcessConfig.Env = container.Env
|
||||||
c.Dir = c.Rootfs
|
c.ProcessConfig.Dir = c.Rootfs
|
||||||
|
|
||||||
return &c.Cmd
|
return &c.ProcessConfig.Cmd
|
||||||
}, func() {
|
}, func() {
|
||||||
if startCallback != nil {
|
if startCallback != nil {
|
||||||
c.ContainerPid = c.Process.Pid
|
c.ProcessConfig.ContainerPid = c.ProcessConfig.Process.Pid
|
||||||
startCallback(c)
|
startCallback(&c.ProcessConfig)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) Kill(p *execdriver.Command, sig int) error {
|
func (d *driver) Kill(p *execdriver.Command, sig int) error {
|
||||||
return syscall.Kill(p.Process.Pid, syscall.Signal(sig))
|
return syscall.Kill(p.ProcessConfig.Process.Pid, syscall.Signal(sig))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) Pause(c *execdriver.Command) error {
|
func (d *driver) Pause(c *execdriver.Command) error {
|
||||||
|
@ -176,14 +176,14 @@ func (d *driver) Terminate(p *execdriver.Command) error {
|
||||||
state = &libcontainer.State{InitStartTime: string(data)}
|
state = &libcontainer.State{InitStartTime: string(data)}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentStartTime, err := system.GetProcessStartTime(p.Process.Pid)
|
currentStartTime, err := system.GetProcessStartTime(p.ProcessConfig.Process.Pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.InitStartTime == currentStartTime {
|
if state.InitStartTime == currentStartTime {
|
||||||
err = syscall.Kill(p.Process.Pid, 9)
|
err = syscall.Kill(p.ProcessConfig.Process.Pid, 9)
|
||||||
syscall.Wait4(p.Process.Pid, nil, 0, nil)
|
syscall.Wait4(p.ProcessConfig.Process.Pid, nil, 0, nil)
|
||||||
}
|
}
|
||||||
d.removeContainerRoot(p.ID)
|
d.removeContainerRoot(p.ID)
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ type TtyConsole struct {
|
||||||
MasterPty *os.File
|
MasterPty *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
||||||
ptyMaster, console, err := consolepkg.CreateMasterAndConsole()
|
ptyMaster, console, err := consolepkg.CreateMasterAndConsole()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -262,12 +262,12 @@ func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyCo
|
||||||
MasterPty: ptyMaster,
|
MasterPty: ptyMaster,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tty.AttachPipes(&command.Cmd, pipes); err != nil {
|
if err := tty.AttachPipes(&processConfig.Cmd, pipes); err != nil {
|
||||||
tty.Close()
|
tty.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
command.Console = console
|
processConfig.Console = console
|
||||||
|
|
||||||
return tty, nil
|
return tty, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
type StdConsole struct {
|
type StdConsole struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStdConsole(command *Command, pipes *Pipes) (*StdConsole, error) {
|
func NewStdConsole(processConfig *ProcessConfig, pipes *Pipes) (*StdConsole, error) {
|
||||||
std := &StdConsole{}
|
std := &StdConsole{}
|
||||||
|
|
||||||
if err := std.AttachPipes(&command.Cmd, pipes); err != nil {
|
if err := std.AttachPipes(&processConfig.Cmd, pipes); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return std, nil
|
return std, nil
|
||||||
|
|
|
@ -128,7 +128,7 @@ func (m *containerMonitor) Start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pipes := execdriver.NewPipes(m.container.stdin, m.container.stdout, m.container.stderr, m.container.Config.OpenStdin)
|
pipes := execdriver.NewPipes(m.container.StdConfig.stdin, m.container.StdConfig.stdout, m.container.StdConfig.stderr, m.container.Config.OpenStdin)
|
||||||
|
|
||||||
m.container.LogEvent("start")
|
m.container.LogEvent("start")
|
||||||
|
|
||||||
|
@ -233,17 +233,17 @@ func (m *containerMonitor) shouldRestart(exitStatus int) bool {
|
||||||
|
|
||||||
// callback ensures that the container's state is properly updated after we
|
// callback ensures that the container's state is properly updated after we
|
||||||
// received ack from the execution drivers
|
// received ack from the execution drivers
|
||||||
func (m *containerMonitor) callback(command *execdriver.Command) {
|
func (m *containerMonitor) callback(processConfig *execdriver.ProcessConfig) {
|
||||||
if command.Tty {
|
if processConfig.Tty {
|
||||||
// The callback is called after the process Start()
|
// The callback is called after the process Start()
|
||||||
// so we are in the parent process. In TTY mode, stdin/out/err is the PtySlace
|
// so we are in the parent process. In TTY mode, stdin/out/err is the PtySlace
|
||||||
// which we close here.
|
// which we close here.
|
||||||
if c, ok := command.Stdout.(io.Closer); ok {
|
if c, ok := processConfig.Stdout.(io.Closer); ok {
|
||||||
c.Close()
|
c.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.container.State.setRunning(command.Pid())
|
m.container.State.setRunning(processConfig.Pid())
|
||||||
|
|
||||||
// signal that the process has started
|
// signal that the process has started
|
||||||
// close channel only if not closed
|
// close channel only if not closed
|
||||||
|
@ -269,33 +269,33 @@ func (m *containerMonitor) resetContainer(lock bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.Config.OpenStdin {
|
if container.Config.OpenStdin {
|
||||||
if err := container.stdin.Close(); err != nil {
|
if err := container.StdConfig.stdin.Close(); err != nil {
|
||||||
log.Errorf("%s: Error close stdin: %s", container.ID, err)
|
log.Errorf("%s: Error close stdin: %s", container.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.stdout.Clean(); err != nil {
|
if err := container.StdConfig.stdout.Clean(); err != nil {
|
||||||
log.Errorf("%s: Error close stdout: %s", container.ID, err)
|
log.Errorf("%s: Error close stdout: %s", container.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.stderr.Clean(); err != nil {
|
if err := container.StdConfig.stderr.Clean(); err != nil {
|
||||||
log.Errorf("%s: Error close stderr: %s", container.ID, err)
|
log.Errorf("%s: Error close stderr: %s", container.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.command != nil && container.command.Terminal != nil {
|
if container.command != nil && container.command.ProcessConfig.Terminal != nil {
|
||||||
if err := container.command.Terminal.Close(); err != nil {
|
if err := container.command.ProcessConfig.Terminal.Close(); err != nil {
|
||||||
log.Errorf("%s: Error closing terminal: %s", container.ID, err)
|
log.Errorf("%s: Error closing terminal: %s", container.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-create a brand new stdin pipe once the container exited
|
// Re-create a brand new stdin pipe once the container exited
|
||||||
if container.Config.OpenStdin {
|
if container.Config.OpenStdin {
|
||||||
container.stdin, container.stdinPipe = io.Pipe()
|
container.StdConfig.stdin, container.StdConfig.stdinPipe = io.Pipe()
|
||||||
}
|
}
|
||||||
|
|
||||||
c := container.command.Cmd
|
c := container.command.ProcessConfig.Cmd
|
||||||
|
|
||||||
container.command.Cmd = exec.Cmd{
|
container.command.ProcessConfig.Cmd = exec.Cmd{
|
||||||
Stdin: c.Stdin,
|
Stdin: c.Stdin,
|
||||||
Stdout: c.Stdout,
|
Stdout: c.Stdout,
|
||||||
Stderr: c.Stderr,
|
Stderr: c.Stderr,
|
||||||
|
|
|
@ -467,7 +467,7 @@ func TestAttachDisconnect(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to avoid the timeout in destroy. Best effort, don't check error
|
// Try to avoid the timeout in destroy. Best effort, don't check error
|
||||||
cStdin, _ := container.StdinPipe()
|
cStdin, _ := container.StdConfig.StdinPipe()
|
||||||
cStdin.Close()
|
cStdin.Close()
|
||||||
container.State.WaitStop(-1 * time.Second)
|
container.State.WaitStop(-1 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,11 @@ func TestRestartStdin(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer daemon.Destroy(container)
|
defer daemon.Destroy(container)
|
||||||
|
|
||||||
stdin, err := container.StdinPipe()
|
stdin, err := container.StdConfig.StdinPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
stdout, err := container.StdoutPipe()
|
stdout, err := container.StdConfig.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -55,11 +55,11 @@ func TestRestartStdin(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restart and try again
|
// Restart and try again
|
||||||
stdin, err = container.StdinPipe()
|
stdin, err = container.StdConfig.StdinPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
stdout, err = container.StdoutPipe()
|
stdout, err = container.StdConfig.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -101,11 +101,11 @@ func TestStdin(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer daemon.Destroy(container)
|
defer daemon.Destroy(container)
|
||||||
|
|
||||||
stdin, err := container.StdinPipe()
|
stdin, err := container.StdConfig.StdinPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
stdout, err := container.StdoutPipe()
|
stdout, err := container.StdConfig.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -146,11 +146,11 @@ func TestTty(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer daemon.Destroy(container)
|
defer daemon.Destroy(container)
|
||||||
|
|
||||||
stdin, err := container.StdinPipe()
|
stdin, err := container.StdConfig.StdinPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
stdout, err := container.StdoutPipe()
|
stdout, err := container.StdConfig.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -611,7 +611,7 @@ func TestRestore(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate a crash/manual quit of dockerd: process dies, states stays 'Running'
|
// Simulate a crash/manual quit of dockerd: process dies, states stays 'Running'
|
||||||
cStdin, _ := container2.StdinPipe()
|
cStdin, _ := container2.StdConfig.StdinPipe()
|
||||||
cStdin.Close()
|
cStdin.Close()
|
||||||
if _, err := container2.State.WaitStop(2 * time.Second); err != nil {
|
if _, err := container2.State.WaitStop(2 * time.Second); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -84,11 +84,11 @@ func containerFileExists(eng *engine.Engine, id, dir string, t log.Fataler) bool
|
||||||
|
|
||||||
func containerAttach(eng *engine.Engine, id string, t log.Fataler) (io.WriteCloser, io.ReadCloser) {
|
func containerAttach(eng *engine.Engine, id string, t log.Fataler) (io.WriteCloser, io.ReadCloser) {
|
||||||
c := getContainer(eng, id, t)
|
c := getContainer(eng, id, t)
|
||||||
i, err := c.StdinPipe()
|
i, err := c.StdConfig.StdinPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
o, err := c.StdoutPipe()
|
o, err := c.StdConfig.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ func runContainer(eng *engine.Engine, r *daemon.Daemon, args []string, t *testin
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer r.Destroy(container)
|
defer r.Destroy(container)
|
||||||
stdout, err := container.StdoutPipe()
|
stdout, err := container.StdConfig.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue