backend.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package moby
  2. import (
  3. "context"
  4. "io"
  5. "github.com/docker/docker/api/types"
  6. "github.com/docker/docker/api/types/container"
  7. "github.com/docker/docker/client"
  8. "github.com/pkg/errors"
  9. "github.com/docker/api/backend"
  10. "github.com/docker/api/compose"
  11. "github.com/docker/api/containers"
  12. "github.com/docker/api/errdefs"
  13. )
  14. type mobyService struct {
  15. apiClient *client.Client
  16. }
  17. func init() {
  18. backend.Register("moby", "moby", func(ctx context.Context) (backend.Service, error) {
  19. return New()
  20. })
  21. }
  22. // New returns a moby backend implementation
  23. func New() (backend.Service, error) {
  24. apiClient, err := client.NewClientWithOpts(client.FromEnv)
  25. if err != nil {
  26. return nil, err
  27. }
  28. return &mobyService{
  29. apiClient,
  30. }, nil
  31. }
  32. func (ms *mobyService) ContainerService() containers.Service {
  33. return ms
  34. }
  35. func (ms *mobyService) ComposeService() compose.Service {
  36. return nil
  37. }
  38. func (ms *mobyService) List(ctx context.Context) ([]containers.Container, error) {
  39. css, err := ms.apiClient.ContainerList(ctx, types.ContainerListOptions{
  40. All: false,
  41. })
  42. if err != nil {
  43. return []containers.Container{}, err
  44. }
  45. var result []containers.Container
  46. for _, container := range css {
  47. result = append(result, containers.Container{
  48. ID: container.ID,
  49. Image: container.Image,
  50. Status: container.Status,
  51. Command: container.Command,
  52. })
  53. }
  54. return result, nil
  55. }
  56. func (ms *mobyService) Run(ctx context.Context, r containers.ContainerConfig) error {
  57. create, err := ms.apiClient.ContainerCreate(ctx, &container.Config{
  58. Image: r.Image,
  59. }, nil, nil, r.ID)
  60. if err != nil {
  61. return err
  62. }
  63. return ms.apiClient.ContainerStart(ctx, create.ID, types.ContainerStartOptions{})
  64. }
  65. func (ms *mobyService) Exec(ctx context.Context, name string, command string, reader io.Reader, writer io.Writer) error {
  66. cec, err := ms.apiClient.ContainerExecCreate(ctx, name, types.ExecConfig{
  67. Cmd: []string{command},
  68. Tty: true,
  69. AttachStderr: true,
  70. AttachStdin: true,
  71. AttachStdout: true,
  72. })
  73. if err != nil {
  74. return err
  75. }
  76. resp, err := ms.apiClient.ContainerExecAttach(ctx, cec.ID, types.ExecStartCheck{})
  77. if err != nil {
  78. return err
  79. }
  80. defer resp.Close()
  81. readChannel := make(chan error, 10)
  82. writeChannel := make(chan error, 10)
  83. go func() {
  84. _, err := io.Copy(writer, resp.Reader)
  85. readChannel <- err
  86. }()
  87. go func() {
  88. _, err := io.Copy(resp.Conn, reader)
  89. writeChannel <- err
  90. }()
  91. for {
  92. select {
  93. case err := <-readChannel:
  94. return err
  95. case err := <-writeChannel:
  96. return err
  97. }
  98. }
  99. }
  100. func (ms *mobyService) Logs(ctx context.Context, containerName string, request containers.LogsRequest) error {
  101. r, err := ms.apiClient.ContainerLogs(ctx, containerName, types.ContainerLogsOptions{
  102. ShowStdout: true,
  103. ShowStderr: true,
  104. })
  105. if err != nil {
  106. return err
  107. }
  108. _, err = io.Copy(request.Writer, r)
  109. return err
  110. }
  111. func (ms *mobyService) Delete(ctx context.Context, containerID string, force bool) error {
  112. err := ms.apiClient.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{
  113. Force: force,
  114. })
  115. if client.IsErrNotFound(err) {
  116. return errors.Wrapf(errdefs.ErrNotFound, "container %q", containerID)
  117. }
  118. return err
  119. }