github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/api/server/router/container/exec.go (about) 1 package container 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 "strconv" 9 10 "github.com/Sirupsen/logrus" 11 "github.com/docker/docker/api/server/httputils" 12 "github.com/docker/docker/pkg/stdcopy" 13 "github.com/docker/engine-api/types" 14 "golang.org/x/net/context" 15 ) 16 17 func (s *containerRouter) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 18 eConfig, err := s.backend.ContainerExecInspect(vars["id"]) 19 if err != nil { 20 return err 21 } 22 23 return httputils.WriteJSON(w, http.StatusOK, eConfig) 24 } 25 26 func (s *containerRouter) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 27 if err := httputils.ParseForm(r); err != nil { 28 return err 29 } 30 if err := httputils.CheckForJSON(r); err != nil { 31 return err 32 } 33 name := vars["name"] 34 35 execConfig := &types.ExecConfig{} 36 if err := json.NewDecoder(r.Body).Decode(execConfig); err != nil { 37 return err 38 } 39 execConfig.Container = name 40 41 if len(execConfig.Cmd) == 0 { 42 return fmt.Errorf("No exec command specified") 43 } 44 45 // Register an instance of Exec in container. 46 id, err := s.backend.ContainerExecCreate(execConfig) 47 if err != nil { 48 logrus.Errorf("Error setting up exec command in container %s: %v", name, err) 49 return err 50 } 51 52 return httputils.WriteJSON(w, http.StatusCreated, &types.ContainerExecCreateResponse{ 53 ID: id, 54 }) 55 } 56 57 // TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start. 58 func (s *containerRouter) postContainerExecStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 59 if err := httputils.ParseForm(r); err != nil { 60 return err 61 } 62 63 version := httputils.VersionFromContext(ctx) 64 if version.GreaterThan("1.21") { 65 if err := httputils.CheckForJSON(r); err != nil { 66 return err 67 } 68 } 69 70 var ( 71 execName = vars["name"] 72 stdin, inStream io.ReadCloser 73 stdout, stderr, outStream io.Writer 74 ) 75 76 execStartCheck := &types.ExecStartCheck{} 77 if err := json.NewDecoder(r.Body).Decode(execStartCheck); err != nil { 78 return err 79 } 80 81 if exists, err := s.backend.ExecExists(execName); !exists { 82 return err 83 } 84 85 if !execStartCheck.Detach { 86 var err error 87 // Setting up the streaming http interface. 88 inStream, outStream, err = httputils.HijackConnection(w) 89 if err != nil { 90 return err 91 } 92 defer httputils.CloseStreams(inStream, outStream) 93 94 if _, ok := r.Header["Upgrade"]; ok { 95 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") 96 } else { 97 fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") 98 } 99 100 stdin = inStream 101 stdout = outStream 102 if !execStartCheck.Tty { 103 stderr = stdcopy.NewStdWriter(outStream, stdcopy.Stderr) 104 stdout = stdcopy.NewStdWriter(outStream, stdcopy.Stdout) 105 } 106 } else { 107 outStream = w 108 } 109 110 // Now run the user process in container. 111 if err := s.backend.ContainerExecStart(execName, stdin, stdout, stderr); err != nil { 112 if execStartCheck.Detach { 113 return err 114 } 115 logrus.Errorf("Error running exec in container: %v\n", err) 116 } 117 return nil 118 } 119 120 func (s *containerRouter) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 121 if err := httputils.ParseForm(r); err != nil { 122 return err 123 } 124 height, err := strconv.Atoi(r.Form.Get("h")) 125 if err != nil { 126 return err 127 } 128 width, err := strconv.Atoi(r.Form.Get("w")) 129 if err != nil { 130 return err 131 } 132 133 return s.backend.ContainerExecResize(vars["name"], height, width) 134 }