summaryrefslogtreecommitdiff
path: root/plugin/executor
diff options
context:
space:
mode:
authorMichael Crosby <crosbymichael@gmail.com>2019-03-25 16:17:17 -0400
committerMichael Crosby <crosbymichael@gmail.com>2019-04-05 15:48:07 -0400
commitb9b5dc37e37e67d1cd46d9a3448c96e3f57ef4bc (patch)
treed406c2839e114f4efffa134125e962c42fd49e16 /plugin/executor
parentadb15c2899d22011b70edab0a380416295f626ed (diff)
downloaddocker-b9b5dc37e37e67d1cd46d9a3448c96e3f57ef4bc.tar.gz
Remove inmemory container map
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
Diffstat (limited to 'plugin/executor')
-rw-r--r--plugin/executor/containerd/containerd.go40
-rw-r--r--plugin/executor/containerd/containerd_test.go149
2 files changed, 15 insertions, 174 deletions
diff --git a/plugin/executor/containerd/containerd.go b/plugin/executor/containerd/containerd.go
index 61aaedf3ee..23418558d8 100644
--- a/plugin/executor/containerd/containerd.go
+++ b/plugin/executor/containerd/containerd.go
@@ -5,7 +5,6 @@ import (
"io"
"path/filepath"
"sync"
- "time"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
@@ -26,19 +25,6 @@ type ExitHandler interface {
HandleExitEvent(id string) error
}
-// Client is used by the exector to perform operations.
-// TODO(@cpuguy83): This should really just be based off the containerd client interface.
-// However right now this whole package is tied to github.com/docker/docker/libcontainerd
-type Client interface {
- Create(ctx context.Context, containerID string, spec *specs.Spec, runtimeOptions interface{}) error
- Restore(ctx context.Context, containerID string, attachStdio libcontainerdtypes.StdioCallback) (alive bool, pid int, err error)
- Status(ctx context.Context, containerID string) (containerd.ProcessStatus, error)
- Delete(ctx context.Context, containerID string) error
- DeleteTask(ctx context.Context, containerID string) (uint32, time.Time, error)
- Start(ctx context.Context, containerID, checkpointDir string, withStdin bool, attachStdio libcontainerdtypes.StdioCallback) (pid int, err error)
- SignalProcess(ctx context.Context, containerID, processID string, signal int) error
-}
-
// New creates a new containerd plugin executor
func New(ctx context.Context, rootDir string, cli *containerd.Client, exitHandler ExitHandler) (*Executor, error) {
e := &Executor{
@@ -57,19 +43,23 @@ func New(ctx context.Context, rootDir string, cli *containerd.Client, exitHandle
// Executor is the containerd client implementation of a plugin executor
type Executor struct {
rootDir string
- client Client
+ client libcontainerdtypes.Client
exitHandler ExitHandler
}
// deleteTaskAndContainer deletes plugin task and then plugin container from containerd
-func deleteTaskAndContainer(ctx context.Context, cli Client, id string) {
- _, _, err := cli.DeleteTask(ctx, id)
- if err != nil && !errdefs.IsNotFound(err) {
- logrus.WithError(err).WithField("id", id).Error("failed to delete plugin task from containerd")
+func deleteTaskAndContainer(ctx context.Context, cli libcontainerdtypes.Client, id string, p libcontainerdtypes.Process) {
+ if p != nil {
+ if _, _, err := p.Delete(ctx); err != nil && !errdefs.IsNotFound(err) {
+ logrus.WithError(err).WithField("id", id).Error("failed to delete plugin task from containerd")
+ }
+ } else {
+ if _, _, err := cli.DeleteTask(ctx, id); err != nil && !errdefs.IsNotFound(err) {
+ logrus.WithError(err).WithField("id", id).Error("failed to delete plugin task from containerd")
+ }
}
- err = cli.Delete(ctx, id)
- if err != nil && !errdefs.IsNotFound(err) {
+ if err := cli.Delete(ctx, id); err != nil && !errdefs.IsNotFound(err) {
logrus.WithError(err).WithField("id", id).Error("failed to delete plugin container from containerd")
}
}
@@ -103,19 +93,19 @@ func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteClo
_, err = e.client.Start(ctx, id, "", false, attachStreamsFunc(stdout, stderr))
if err != nil {
- deleteTaskAndContainer(ctx, e.client, id)
+ deleteTaskAndContainer(ctx, e.client, id, nil)
}
return err
}
// Restore restores a container
func (e *Executor) Restore(id string, stdout, stderr io.WriteCloser) (bool, error) {
- alive, _, err := e.client.Restore(context.Background(), id, attachStreamsFunc(stdout, stderr))
+ alive, _, p, err := e.client.Restore(context.Background(), id, attachStreamsFunc(stdout, stderr))
if err != nil && !errdefs.IsNotFound(err) {
return false, err
}
if !alive {
- deleteTaskAndContainer(context.Background(), e.client, id)
+ deleteTaskAndContainer(context.Background(), e.client, id, p)
}
return alive, nil
}
@@ -136,7 +126,7 @@ func (e *Executor) Signal(id string, signal int) error {
func (e *Executor) ProcessEvent(id string, et libcontainerdtypes.EventType, ei libcontainerdtypes.EventInfo) error {
switch et {
case libcontainerdtypes.EventExit:
- deleteTaskAndContainer(context.Background(), e.client, id)
+ deleteTaskAndContainer(context.Background(), e.client, id, nil)
return e.exitHandler.HandleExitEvent(ei.ContainerID)
}
return nil
diff --git a/plugin/executor/containerd/containerd_test.go b/plugin/executor/containerd/containerd_test.go
deleted file mode 100644
index 8e2d616784..0000000000
--- a/plugin/executor/containerd/containerd_test.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package containerd
-
-import (
- "context"
- "io/ioutil"
- "os"
- "sync"
- "testing"
- "time"
-
- "github.com/containerd/containerd"
- libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
- "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
- "gotest.tools/assert"
-)
-
-func TestLifeCycle(t *testing.T) {
- t.Parallel()
-
- mock := newMockClient()
- exec, cleanup := setupTest(t, mock, mock)
- defer cleanup()
-
- id := "test-create"
- mock.simulateStartError(true, id)
- err := exec.Create(id, specs.Spec{}, nil, nil)
- assert.Assert(t, err != nil)
- mock.simulateStartError(false, id)
-
- err = exec.Create(id, specs.Spec{}, nil, nil)
- assert.NilError(t, err)
- running, _ := exec.IsRunning(id)
- assert.Assert(t, running)
-
- // create with the same ID
- err = exec.Create(id, specs.Spec{}, nil, nil)
- assert.Assert(t, err != nil)
-
- mock.HandleExitEvent(id) // simulate a plugin that exits
-
- err = exec.Create(id, specs.Spec{}, nil, nil)
- assert.NilError(t, err)
-}
-
-func setupTest(t *testing.T, client Client, eh ExitHandler) (*Executor, func()) {
- rootDir, err := ioutil.TempDir("", "test-daemon")
- assert.NilError(t, err)
- assert.Assert(t, client != nil)
- assert.Assert(t, eh != nil)
-
- return &Executor{
- rootDir: rootDir,
- client: client,
- exitHandler: eh,
- }, func() {
- assert.Assert(t, os.RemoveAll(rootDir))
- }
-}
-
-type mockClient struct {
- mu sync.Mutex
- containers map[string]bool
- errorOnStart map[string]bool
-}
-
-func newMockClient() *mockClient {
- return &mockClient{
- containers: make(map[string]bool),
- errorOnStart: make(map[string]bool),
- }
-}
-
-func (c *mockClient) Create(ctx context.Context, id string, _ *specs.Spec, _ interface{}) error {
- c.mu.Lock()
- defer c.mu.Unlock()
-
- if _, ok := c.containers[id]; ok {
- return errors.New("exists")
- }
-
- c.containers[id] = false
- return nil
-}
-
-func (c *mockClient) Restore(ctx context.Context, id string, attachStdio libcontainerdtypes.StdioCallback) (alive bool, pid int, err error) {
- return false, 0, nil
-}
-
-func (c *mockClient) Status(ctx context.Context, id string) (containerd.ProcessStatus, error) {
- c.mu.Lock()
- defer c.mu.Unlock()
-
- running, ok := c.containers[id]
- if !ok {
- return containerd.Unknown, errors.New("not found")
- }
- if running {
- return containerd.Running, nil
- }
- return containerd.Stopped, nil
-}
-
-func (c *mockClient) Delete(ctx context.Context, id string) error {
- c.mu.Lock()
- defer c.mu.Unlock()
- delete(c.containers, id)
- return nil
-}
-
-func (c *mockClient) DeleteTask(ctx context.Context, id string) (uint32, time.Time, error) {
- return 0, time.Time{}, nil
-}
-
-func (c *mockClient) Start(ctx context.Context, id, checkpointDir string, withStdin bool, attachStdio libcontainerdtypes.StdioCallback) (pid int, err error) {
- c.mu.Lock()
- defer c.mu.Unlock()
-
- if _, ok := c.containers[id]; !ok {
- return 0, errors.New("not found")
- }
-
- if c.errorOnStart[id] {
- return 0, errors.New("some startup error")
- }
- c.containers[id] = true
- return 1, nil
-}
-
-func (c *mockClient) SignalProcess(ctx context.Context, containerID, processID string, signal int) error {
- return nil
-}
-
-func (c *mockClient) simulateStartError(sim bool, id string) {
- c.mu.Lock()
- defer c.mu.Unlock()
- if sim {
- c.errorOnStart[id] = sim
- return
- }
- delete(c.errorOnStart, id)
-}
-
-func (c *mockClient) HandleExitEvent(id string) error {
- c.mu.Lock()
- defer c.mu.Unlock()
- delete(c.containers, id)
- return nil
-}