containerd/process.go
Michael Crosby 2b6d790ff4 Refactor runtime events into Task* types
This removes the RuntimeEvent super proto with enums into separate
runtime event protos to be inline with the other events that are output
by containerd.

This also renames the runtime events into Task* events.

Fixes #1071

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2017-07-12 10:57:57 -07:00

123 lines
2.7 KiB
Go

package containerd
import (
"context"
"syscall"
eventsapi "github.com/containerd/containerd/api/services/events/v1"
"github.com/containerd/containerd/api/services/tasks/v1"
"github.com/containerd/containerd/typeurl"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
type process struct {
id string
task *task
pid uint32
io *IO
spec *specs.Process
}
func (p *process) ID() string {
return p.id
}
// Pid returns the pid of the process
// The pid is not set until start is called and returns
func (p *process) Pid() uint32 {
return p.pid
}
// Start starts the exec process
func (p *process) Start(ctx context.Context) error {
any, err := typeurl.MarshalAny(p.spec)
if err != nil {
return err
}
request := &tasks.ExecProcessRequest{
ContainerID: p.task.id,
ExecID: p.id,
Terminal: p.io.Terminal,
Stdin: p.io.Stdin,
Stdout: p.io.Stdout,
Stderr: p.io.Stderr,
Spec: any,
}
response, err := p.task.client.TaskService().Exec(ctx, request)
if err != nil {
return err
}
p.pid = response.Pid
return nil
}
func (p *process) Kill(ctx context.Context, s syscall.Signal) error {
_, err := p.task.client.TaskService().Kill(ctx, &tasks.KillRequest{
Signal: uint32(s),
ContainerID: p.task.id,
ExecID: p.id,
})
return err
}
func (p *process) Wait(ctx context.Context) (uint32, error) {
eventstream, err := p.task.client.EventService().Stream(ctx, &eventsapi.StreamEventsRequest{})
if err != nil {
return UnknownExitStatus, err
}
for {
evt, err := eventstream.Recv()
if err != nil {
return UnknownExitStatus, err
}
if typeurl.Is(evt.Event, &eventsapi.TaskExit{}) {
v, err := typeurl.UnmarshalAny(evt.Event)
if err != nil {
return UnknownExitStatus, err
}
e := v.(*eventsapi.TaskExit)
if e.ID == p.id && e.ContainerID == p.task.id {
return e.ExitStatus, nil
}
}
}
}
func (p *process) CloseIO(ctx context.Context, opts ...IOCloserOpts) error {
r := &tasks.CloseIORequest{
ContainerID: p.task.id,
ExecID: p.id,
}
for _, o := range opts {
o(r)
}
_, err := p.task.client.TaskService().CloseIO(ctx, r)
return err
}
func (p *process) IO() *IO {
return p.io
}
func (p *process) Resize(ctx context.Context, w, h uint32) error {
_, err := p.task.client.TaskService().ResizePty(ctx, &tasks.ResizePtyRequest{
ContainerID: p.task.id,
Width: w,
Height: h,
ExecID: p.id,
})
return err
}
func (p *process) Delete(ctx context.Context) (uint32, error) {
cerr := p.io.Close()
r, err := p.task.client.TaskService().DeleteProcess(ctx, &tasks.DeleteProcessRequest{
ContainerID: p.task.id,
ExecID: p.id,
})
if err != nil {
return UnknownExitStatus, err
}
return r.ExitStatus, cerr
}