exec.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package server
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "strconv"
  8. "github.com/Sirupsen/logrus"
  9. "github.com/docker/docker/api/types"
  10. "github.com/docker/docker/context"
  11. "github.com/docker/docker/pkg/stdcopy"
  12. "github.com/docker/docker/runconfig"
  13. )
  14. func (s *Server) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  15. if vars == nil {
  16. return fmt.Errorf("Missing parameter 'id'")
  17. }
  18. eConfig, err := s.daemon.ContainerExecInspect(ctx, vars["id"])
  19. if err != nil {
  20. return err
  21. }
  22. return writeJSON(w, http.StatusOK, eConfig)
  23. }
  24. func (s *Server) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  25. if err := parseForm(r); err != nil {
  26. return err
  27. }
  28. if err := checkForJSON(r); err != nil {
  29. return err
  30. }
  31. name := vars["name"]
  32. execConfig := &runconfig.ExecConfig{}
  33. if err := json.NewDecoder(r.Body).Decode(execConfig); err != nil {
  34. return err
  35. }
  36. execConfig.Container = name
  37. if len(execConfig.Cmd) == 0 {
  38. return fmt.Errorf("No exec command specified")
  39. }
  40. // Register an instance of Exec in container.
  41. id, err := s.daemon.ContainerExecCreate(ctx, execConfig)
  42. if err != nil {
  43. logrus.Errorf("Error setting up exec command in container %s: %s", name, err)
  44. return err
  45. }
  46. return writeJSON(w, http.StatusCreated, &types.ContainerExecCreateResponse{
  47. ID: id,
  48. })
  49. }
  50. // TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start.
  51. func (s *Server) postContainerExecStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  52. if err := parseForm(r); err != nil {
  53. return err
  54. }
  55. var (
  56. execName = vars["name"]
  57. stdin, inStream io.ReadCloser
  58. stdout, stderr, outStream io.Writer
  59. )
  60. execStartCheck := &types.ExecStartCheck{}
  61. if err := json.NewDecoder(r.Body).Decode(execStartCheck); err != nil {
  62. return err
  63. }
  64. if !execStartCheck.Detach {
  65. var err error
  66. // Setting up the streaming http interface.
  67. inStream, outStream, err = hijackServer(w)
  68. if err != nil {
  69. return err
  70. }
  71. defer closeStreams(inStream, outStream)
  72. if _, ok := r.Header["Upgrade"]; ok {
  73. fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
  74. } else {
  75. fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
  76. }
  77. stdin = inStream
  78. stdout = outStream
  79. if !execStartCheck.Tty {
  80. stderr = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
  81. stdout = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
  82. }
  83. } else {
  84. outStream = w
  85. }
  86. // Now run the user process in container.
  87. if err := s.daemon.ContainerExecStart(ctx, execName, stdin, stdout, stderr); err != nil {
  88. fmt.Fprintf(outStream, "Error running exec in container: %v\n", err)
  89. }
  90. return nil
  91. }
  92. func (s *Server) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  93. if err := parseForm(r); err != nil {
  94. return err
  95. }
  96. if vars == nil {
  97. return fmt.Errorf("Missing parameter")
  98. }
  99. height, err := strconv.Atoi(r.Form.Get("h"))
  100. if err != nil {
  101. return err
  102. }
  103. width, err := strconv.Atoi(r.Form.Get("w"))
  104. if err != nil {
  105. return err
  106. }
  107. return s.daemon.ContainerExecResize(ctx, vars["name"], height, width)
  108. }