78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
|
package containerd
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
|
||
|
"github.com/docker/docker/libcontainerd"
|
||
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
// ExitHandler represents an object that is called when the exit event is received from containerd
|
||
|
type ExitHandler interface {
|
||
|
HandleExitEvent(id string) error
|
||
|
}
|
||
|
|
||
|
// New creates a new containerd plugin executor
|
||
|
func New(remote libcontainerd.Remote, exitHandler ExitHandler) (*Executor, error) {
|
||
|
e := &Executor{exitHandler: exitHandler}
|
||
|
client, err := remote.Client(e)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "error creating containerd exec client")
|
||
|
}
|
||
|
e.client = client
|
||
|
return e, nil
|
||
|
}
|
||
|
|
||
|
// Executor is the containerd client implementation of a plugin executor
|
||
|
type Executor struct {
|
||
|
client libcontainerd.Client
|
||
|
exitHandler ExitHandler
|
||
|
}
|
||
|
|
||
|
// Create creates a new container
|
||
|
func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteCloser) error {
|
||
|
return e.client.Create(id, "", "", spec, attachStreamsFunc(stdout, stderr))
|
||
|
}
|
||
|
|
||
|
// Restore restores a container
|
||
|
func (e *Executor) Restore(id string, stdout, stderr io.WriteCloser) error {
|
||
|
return e.client.Restore(id, attachStreamsFunc(stdout, stderr))
|
||
|
}
|
||
|
|
||
|
// IsRunning returns if the container with the given id is running
|
||
|
func (e *Executor) IsRunning(id string) (bool, error) {
|
||
|
pids, err := e.client.GetPidsForContainer(id)
|
||
|
return len(pids) > 0, err
|
||
|
}
|
||
|
|
||
|
// Signal sends the specified signal to the container
|
||
|
func (e *Executor) Signal(id string, signal int) error {
|
||
|
return e.client.Signal(id, signal)
|
||
|
}
|
||
|
|
||
|
// StateChanged handles state changes from containerd
|
||
|
// All events are ignored except the exit event, which is sent of to the stored handler
|
||
|
func (e *Executor) StateChanged(id string, event libcontainerd.StateInfo) error {
|
||
|
switch event.State {
|
||
|
case libcontainerd.StateExit:
|
||
|
return e.exitHandler.HandleExitEvent(id)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func attachStreamsFunc(stdout, stderr io.WriteCloser) func(libcontainerd.IOPipe) error {
|
||
|
return func(iop libcontainerd.IOPipe) error {
|
||
|
iop.Stdin.Close()
|
||
|
go func() {
|
||
|
io.Copy(stdout, iop.Stdout)
|
||
|
stdout.Close()
|
||
|
}()
|
||
|
go func() {
|
||
|
io.Copy(stderr, iop.Stderr)
|
||
|
stderr.Close()
|
||
|
}()
|
||
|
return nil
|
||
|
}
|
||
|
}
|