diff --git a/container.go b/container.go index 6df235d6e..4ed462a80 100644 --- a/container.go +++ b/container.go @@ -165,12 +165,13 @@ func (c *container) NewTask(ctx context.Context, ioCreate IOCreation, opts ...Ne if err != nil { return nil, err } + cfg := i.Config() request := &tasks.CreateTaskRequest{ ContainerID: c.c.ID, - Terminal: i.Terminal, - Stdin: i.Stdin, - Stdout: i.Stdout, - Stderr: i.Stderr, + Terminal: cfg.Terminal, + Stdin: cfg.Stdin, + Stdout: cfg.Stdout, + Stderr: cfg.Stderr, } if c.c.RootFS != "" { // get the rootfs from the snapshotter and add it to the request @@ -238,7 +239,7 @@ func (c *container) loadTask(ctx context.Context, ioAttach IOAttach) (Task, erro } return nil, err } - var i *IO + var i IO if ioAttach != nil { // get the existing fifo paths from the task information stored by the daemon paths := &FIFOSet{ diff --git a/io.go b/io.go index e2d52f7d1..27c3482c1 100644 --- a/io.go +++ b/io.go @@ -8,8 +8,8 @@ import ( "sync" ) -// IO holds the io information for a task or process -type IO struct { +// IOConfig holds the io configurations. +type IOConfig struct { // Terminal is true if one has been allocated Terminal bool // Stdin path @@ -18,39 +18,58 @@ type IO struct { Stdout string // Stderr path Stderr string +} + +// IO holds the io information for a task or process +type IO interface { + // Config returns the IO configuration. + Config() IOConfig + + // Cancel aborts all current io operations + Cancel() + // Wait blocks until all io copy operations have completed + Wait() + // Close cleans up all open io resources + Close() error +} + +// cio is a basic container IO implementation. +type cio struct { + config IOConfig closer *wgCloser } -// Cancel aborts all current io operations -func (i *IO) Cancel() { - if i.closer == nil { - return - } - i.closer.Cancel() +func (c *cio) Config() IOConfig { + return c.config } -// Wait blocks until all io copy operations have completed -func (i *IO) Wait() { - if i.closer == nil { +func (c *cio) Cancel() { + if c.closer == nil { return } - i.closer.Wait() + c.closer.Cancel() } -// Close cleans up all open io resources -func (i *IO) Close() error { - if i.closer == nil { +func (c *cio) Wait() { + if c.closer == nil { + return + } + c.closer.Wait() +} + +func (c *cio) Close() error { + if c.closer == nil { return nil } - return i.closer.Close() + return c.closer.Close() } // IOCreation creates new IO sets for a task -type IOCreation func(id string) (*IO, error) +type IOCreation func(id string) (IO, error) // IOAttach allows callers to reattach to running tasks -type IOAttach func(*FIFOSet) (*IO, error) +type IOAttach func(*FIFOSet) (IO, error) // NewIO returns an IOCreation that will provide IO sets without a terminal func NewIO(stdin io.Reader, stdout, stderr io.Writer) IOCreation { @@ -59,7 +78,7 @@ func NewIO(stdin io.Reader, stdout, stderr io.Writer) IOCreation { // NewIOWithTerminal creates a new io set with the provied io.Reader/Writers for use with a terminal func NewIOWithTerminal(stdin io.Reader, stdout, stderr io.Writer, terminal bool) IOCreation { - return func(id string) (_ *IO, err error) { + return func(id string) (_ IO, err error) { paths, err := NewFifos(id) if err != nil { return nil, err @@ -69,18 +88,19 @@ func NewIOWithTerminal(stdin io.Reader, stdout, stderr io.Writer, terminal bool) os.RemoveAll(paths.Dir) } }() - i := &IO{ + cfg := IOConfig{ Terminal: terminal, Stdout: paths.Out, Stderr: paths.Err, Stdin: paths.In, } + i := &cio{config: cfg} set := &ioSet{ in: stdin, out: stdout, err: stderr, } - closer, err := copyIO(paths, set, i.Terminal) + closer, err := copyIO(paths, set, cfg.Terminal) if err != nil { return nil, err } @@ -91,22 +111,23 @@ func NewIOWithTerminal(stdin io.Reader, stdout, stderr io.Writer, terminal bool) // WithAttach attaches the existing io for a task to the provided io.Reader/Writers func WithAttach(stdin io.Reader, stdout, stderr io.Writer) IOAttach { - return func(paths *FIFOSet) (*IO, error) { + return func(paths *FIFOSet) (IO, error) { if paths == nil { return nil, fmt.Errorf("cannot attach to existing fifos") } - i := &IO{ + cfg := IOConfig{ Terminal: paths.Terminal, Stdout: paths.Out, Stderr: paths.Err, Stdin: paths.In, } + i := &cio{config: cfg} set := &ioSet{ in: stdin, out: stdout, err: stderr, } - closer, err := copyIO(paths, set, i.Terminal) + closer, err := copyIO(paths, set, cfg.Terminal) if err != nil { return nil, err } @@ -117,18 +138,18 @@ func WithAttach(stdin io.Reader, stdout, stderr io.Writer) IOAttach { // Stdio returns an IO set to be used for a task // that outputs the container's IO as the current processes Stdio -func Stdio(id string) (*IO, error) { +func Stdio(id string) (IO, error) { return NewIO(os.Stdin, os.Stdout, os.Stderr)(id) } // StdioTerminal will setup the IO for the task to use a terminal -func StdioTerminal(id string) (*IO, error) { +func StdioTerminal(id string) (IO, error) { return NewIOWithTerminal(os.Stdin, os.Stdout, os.Stderr, true)(id) } // NullIO redirects the container's IO into /dev/null -func NullIO(id string) (*IO, error) { - return &IO{}, nil +func NullIO(id string) (IO, error) { + return &cio{}, nil } // FIFOSet is a set of fifos for use with tasks diff --git a/process.go b/process.go index c2d2119c0..407f9b6d2 100644 --- a/process.go +++ b/process.go @@ -31,7 +31,7 @@ type Process interface { // Resize changes the width and heigh of the process's terminal Resize(ctx context.Context, w, h uint32) error // IO returns the io set for the process - IO() *IO + IO() IO // Status returns the executing status of the process Status(context.Context) (Status, error) } @@ -40,7 +40,7 @@ type process struct { id string task *task pid uint32 - io *IO + io IO spec *specs.Process } @@ -128,7 +128,7 @@ func (p *process) CloseIO(ctx context.Context, opts ...IOCloserOpts) error { return err } -func (p *process) IO() *IO { +func (p *process) IO() IO { return p.io } diff --git a/task.go b/task.go index 87c4defc3..df4673b7b 100644 --- a/task.go +++ b/task.go @@ -119,7 +119,7 @@ var _ = (Task)(&task{}) type task struct { client *Client - io *IO + io IO id string pid uint32 @@ -142,7 +142,7 @@ func (t *task) Start(ctx context.Context) error { t.deferred = nil t.mu.Unlock() if err != nil { - t.io.closer.Close() + t.io.Close() return err } t.pid = response.Pid @@ -152,7 +152,7 @@ func (t *task) Start(ctx context.Context) error { ContainerID: t.id, }) if err != nil { - t.io.closer.Close() + t.io.Close() } return err } @@ -279,13 +279,14 @@ func (t *task) Exec(ctx context.Context, id string, spec *specs.Process, ioCreat if err != nil { return nil, err } + cfg := i.Config() request := &tasks.ExecProcessRequest{ ContainerID: t.id, ExecID: id, - Terminal: i.Terminal, - Stdin: i.Stdin, - Stdout: i.Stdout, - Stderr: i.Stderr, + Terminal: cfg.Terminal, + Stdin: cfg.Stdin, + Stdout: cfg.Stdout, + Stderr: cfg.Stderr, Spec: any, } if _, err := t.client.TaskService().Exec(ctx, request); err != nil { @@ -325,7 +326,7 @@ func (t *task) CloseIO(ctx context.Context, opts ...IOCloserOpts) error { return err } -func (t *task) IO() *IO { +func (t *task) IO() IO { return t.io }