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