backend.go 2.7 KB

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