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