containerd.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package containerd
  2. import (
  3. "io"
  4. "github.com/docker/docker/libcontainerd"
  5. "github.com/opencontainers/runtime-spec/specs-go"
  6. "github.com/pkg/errors"
  7. )
  8. // ExitHandler represents an object that is called when the exit event is received from containerd
  9. type ExitHandler interface {
  10. HandleExitEvent(id string) error
  11. }
  12. // New creates a new containerd plugin executor
  13. func New(remote libcontainerd.Remote, exitHandler ExitHandler) (*Executor, error) {
  14. e := &Executor{exitHandler: exitHandler}
  15. client, err := remote.Client(e)
  16. if err != nil {
  17. return nil, errors.Wrap(err, "error creating containerd exec client")
  18. }
  19. e.client = client
  20. return e, nil
  21. }
  22. // Executor is the containerd client implementation of a plugin executor
  23. type Executor struct {
  24. client libcontainerd.Client
  25. exitHandler ExitHandler
  26. }
  27. // Create creates a new container
  28. func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteCloser) error {
  29. return e.client.Create(id, "", "", spec, attachStreamsFunc(stdout, stderr))
  30. }
  31. // Restore restores a container
  32. func (e *Executor) Restore(id string, stdout, stderr io.WriteCloser) error {
  33. return e.client.Restore(id, attachStreamsFunc(stdout, stderr))
  34. }
  35. // IsRunning returns if the container with the given id is running
  36. func (e *Executor) IsRunning(id string) (bool, error) {
  37. pids, err := e.client.GetPidsForContainer(id)
  38. return len(pids) > 0, err
  39. }
  40. // Signal sends the specified signal to the container
  41. func (e *Executor) Signal(id string, signal int) error {
  42. return e.client.Signal(id, signal)
  43. }
  44. // StateChanged handles state changes from containerd
  45. // All events are ignored except the exit event, which is sent of to the stored handler
  46. func (e *Executor) StateChanged(id string, event libcontainerd.StateInfo) error {
  47. switch event.State {
  48. case libcontainerd.StateExit:
  49. return e.exitHandler.HandleExitEvent(id)
  50. }
  51. return nil
  52. }
  53. func attachStreamsFunc(stdout, stderr io.WriteCloser) func(libcontainerd.IOPipe) error {
  54. return func(iop libcontainerd.IOPipe) error {
  55. iop.Stdin.Close()
  56. go func() {
  57. io.Copy(stdout, iop.Stdout)
  58. stdout.Close()
  59. }()
  60. go func() {
  61. io.Copy(stderr, iop.Stderr)
  62. stderr.Close()
  63. }()
  64. return nil
  65. }
  66. }