github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/api/handlers/compat/exec.go (about) 1 package compat 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strings" 8 9 "github.com/containers/libpod/libpod" 10 "github.com/containers/libpod/libpod/define" 11 "github.com/containers/libpod/pkg/api/handlers" 12 "github.com/containers/libpod/pkg/api/handlers/utils" 13 "github.com/gorilla/mux" 14 "github.com/pkg/errors" 15 "github.com/sirupsen/logrus" 16 ) 17 18 // ExecCreateHandler creates an exec session for a given container. 19 func ExecCreateHandler(w http.ResponseWriter, r *http.Request) { 20 runtime := r.Context().Value("runtime").(*libpod.Runtime) 21 22 input := new(handlers.ExecCreateConfig) 23 if err := json.NewDecoder(r.Body).Decode(&input); err != nil { 24 utils.InternalServerError(w, errors.Wrapf(err, "error decoding request body as JSON")) 25 return 26 } 27 28 ctrName := utils.GetName(r) 29 ctr, err := runtime.LookupContainer(ctrName) 30 if err != nil { 31 utils.ContainerNotFound(w, ctrName, err) 32 return 33 } 34 35 libpodConfig := new(libpod.ExecConfig) 36 libpodConfig.Command = input.Cmd 37 libpodConfig.Terminal = input.Tty 38 libpodConfig.AttachStdin = input.AttachStdin 39 libpodConfig.AttachStderr = input.AttachStderr 40 libpodConfig.AttachStdout = input.AttachStdout 41 if input.DetachKeys != "" { 42 libpodConfig.DetachKeys = &input.DetachKeys 43 } 44 libpodConfig.Environment = make(map[string]string) 45 for _, envStr := range input.Env { 46 split := strings.SplitN(envStr, "=", 2) 47 if len(split) != 2 { 48 utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Errorf("environment variable %q badly formed, must be key=value", envStr)) 49 return 50 } 51 libpodConfig.Environment[split[0]] = split[1] 52 } 53 libpodConfig.WorkDir = input.WorkingDir 54 libpodConfig.Privileged = input.Privileged 55 libpodConfig.User = input.User 56 57 sessID, err := ctr.ExecCreate(libpodConfig) 58 if err != nil { 59 if errors.Cause(err) == define.ErrCtrStateInvalid { 60 // Check if the container is paused. If so, return a 409 61 state, err := ctr.State() 62 if err == nil { 63 // Ignore the error != nil case. We're already 64 // throwing an InternalServerError below. 65 if state == define.ContainerStatePaused { 66 utils.Error(w, "Container is paused", http.StatusConflict, errors.Errorf("cannot create exec session as container %s is paused", ctr.ID())) 67 return 68 } 69 } 70 } 71 utils.InternalServerError(w, err) 72 return 73 } 74 75 resp := new(handlers.ExecCreateResponse) 76 resp.ID = sessID 77 78 utils.WriteResponse(w, http.StatusCreated, resp) 79 } 80 81 // ExecInspectHandler inspects a given exec session. 82 func ExecInspectHandler(w http.ResponseWriter, r *http.Request) { 83 runtime := r.Context().Value("runtime").(*libpod.Runtime) 84 85 sessionID := mux.Vars(r)["id"] 86 sessionCtr, err := runtime.GetExecSessionContainer(sessionID) 87 if err != nil { 88 utils.Error(w, fmt.Sprintf("No such exec session: %s", sessionID), http.StatusNotFound, err) 89 return 90 } 91 92 logrus.Debugf("Inspecting exec session %s of container %s", sessionID, sessionCtr.ID()) 93 94 session, err := sessionCtr.ExecSession(sessionID) 95 if err != nil { 96 utils.InternalServerError(w, errors.Wrapf(err, "error retrieving exec session %s from container %s", sessionID, sessionCtr.ID())) 97 return 98 } 99 100 inspectOut, err := session.Inspect() 101 if err != nil { 102 utils.InternalServerError(w, err) 103 return 104 } 105 106 utils.WriteResponse(w, http.StatusOK, inspectOut) 107 }