Change IO to interface.

Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
Lantao Liu 2017-08-11 19:17:08 +00:00
parent c288fbe973
commit 8e2c95f9c1
4 changed files with 67 additions and 44 deletions

View File

@ -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{

77
io.go
View File

@ -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

View File

@ -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
}

17
task.go
View File

@ -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
}