diff options
| author | Brian Goff <cpuguy83@gmail.com> | 2017-07-14 16:45:32 -0400 |
|---|---|---|
| committer | Brian Goff <cpuguy83@gmail.com> | 2017-09-19 12:17:55 -0400 |
| commit | c85e8622a4813d7b72d74517faa03ab5de4c4550 (patch) | |
| tree | a10489134bcced753dd73a05cafb8e1f4196057d /plugin/executor | |
| parent | 3fa72d38ec61377b506d31711f5cf1b855219926 (diff) | |
| download | docker-c85e8622a4813d7b72d74517faa03ab5de4c4550.tar.gz | |
Decouple plugin manager from libcontainerd package
libcontainerd has a bunch of platform dependent code and huge interfaces
that are a pain implement.
To make the plugin manager a bit easier to work with, extract the plugin
executor into an interface and move the containerd implementation to a
separate package.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Diffstat (limited to 'plugin/executor')
| -rw-r--r-- | plugin/executor/containerd/containerd.go | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/plugin/executor/containerd/containerd.go b/plugin/executor/containerd/containerd.go new file mode 100644 index 0000000000..74cf530cf1 --- /dev/null +++ b/plugin/executor/containerd/containerd.go @@ -0,0 +1,77 @@ +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 + } +} |
