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  }