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