summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2020-03-20 15:23:35 -0400
committerMatthew Heon <matthew.heon@pm.me>2020-03-23 16:20:42 -0400
commit0c40b62c77d8f7dba8e73ac3ced0de536ec220d5 (patch)
tree3c87c6bb63dbc0970602c44dfa5d1c99f7156681 /pkg
parent3e835a8025bfc4a7a2790f1d343c6ea246fc65ee (diff)
downloadpodman-0c40b62c77d8f7dba8e73ac3ced0de536ec220d5.tar.gz
podman-0c40b62c77d8f7dba8e73ac3ced0de536ec220d5.tar.bz2
podman-0c40b62c77d8f7dba8e73ac3ced0de536ec220d5.zip
Implement APIv2 Exec Create and Inspect Endpoints
Start and Resize require further implementation work. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/exec.go104
-rw-r--r--pkg/api/handlers/types.go8
-rw-r--r--pkg/api/server/register_exec.go16
3 files changed, 120 insertions, 8 deletions
diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go
new file mode 100644
index 000000000..1fa50d23b
--- /dev/null
+++ b/pkg/api/handlers/compat/exec.go
@@ -0,0 +1,104 @@
+package compat
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/api/handlers"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/gorilla/mux"
+ "github.com/pkg/errors"
+)
+
+// ExecCreateHandler creates an exec session for a given container.
+func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ input := new(handlers.ExecCreateConfig)
+ if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
+ utils.InternalServerError(w, errors.Wrapf(err, "error decoding request body as JSON"))
+ return
+ }
+
+ ctrName := utils.GetName(r)
+ ctr, err := runtime.LookupContainer(ctrName)
+ if err != nil {
+ utils.ContainerNotFound(w, ctrName, err)
+ return
+ }
+
+ libpodConfig := new(libpod.ExecConfig)
+ libpodConfig.Command = input.Cmd
+ libpodConfig.Terminal = input.Tty
+ libpodConfig.AttachStdin = input.AttachStdin
+ libpodConfig.AttachStderr = input.AttachStderr
+ libpodConfig.AttachStdout = input.AttachStdout
+ if input.DetachKeys != "" {
+ libpodConfig.DetachKeys = &input.DetachKeys
+ }
+ libpodConfig.Environment = make(map[string]string)
+ for _, envStr := range input.Env {
+ split := strings.SplitN(envStr, "=", 2)
+ if len(split) != 2 {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Errorf("environment variable %q badly formed, must be key=value", envStr))
+ return
+ }
+ libpodConfig.Environment[split[0]] = split[1]
+ }
+ libpodConfig.WorkDir = input.WorkingDir
+ libpodConfig.Privileged = input.Privileged
+ libpodConfig.User = input.User
+
+ sessID, err := ctr.ExecCreate(libpodConfig)
+ if err != nil {
+ if errors.Cause(err) == define.ErrCtrStateInvalid {
+ // Check if the container is paused. If so, return a 409
+ state, err := ctr.State()
+ if err == nil {
+ // Ignore the error != nil case. We're already
+ // throwing an InternalServerError below.
+ if state == define.ContainerStatePaused {
+ utils.Error(w, "Container is paused", http.StatusConflict, errors.Errorf("cannot create exec session as container %s is paused", ctr.ID()))
+ return
+ }
+ }
+ }
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ resp := new(handlers.ExecCreateResponse)
+ resp.ID = sessID
+
+ utils.WriteResponse(w, http.StatusCreated, resp)
+}
+
+// ExecInspectHandler inspects a given exec session.
+func ExecInspectHandler(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ sessionID := mux.Vars(r)["id"]
+ sessionCtr, err := runtime.GetExecSessionContainer(sessionID)
+ if err != nil {
+ utils.Error(w, fmt.Sprintf("No such exec session: %s", sessionID), http.StatusNotFound, err)
+ return
+ }
+
+ session, err := sessionCtr.ExecSession(sessionID)
+ if err != nil {
+ utils.InternalServerError(w, errors.Wrapf(err, "error retrieving exec session %s from container %s", sessionID, sessionCtr.ID()))
+ return
+ }
+
+ inspectOut, err := session.Inspect()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, inspectOut)
+}
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index c6b70251b..6fa776d0f 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -177,6 +177,14 @@ type ImageTreeResponse struct {
Layers []ImageLayer `json:"layers"`
}
+type ExecCreateConfig struct {
+ docker.ExecConfig
+}
+
+type ExecCreateResponse struct {
+ docker.IDResponse
+}
+
func EventToApiEvent(e *events.Event) *Event {
return &Event{dockerEvents.Message{
Type: e.Type.String(),
diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go
index d27d21a04..71fb50307 100644
--- a/pkg/api/server/register_exec.go
+++ b/pkg/api/server/register_exec.go
@@ -8,7 +8,7 @@ import (
)
func (s *APIServer) registerExecHandlers(r *mux.Router) error {
- // swagger:operation POST /containers/{name}/create compat createExec
+ // swagger:operation POST /containers/{name}/exec compat createExec
// ---
// tags:
// - exec (compat)
@@ -74,9 +74,9 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// description: container is paused
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/containers/{name}/create"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/containers/{name}/exec"), s.APIHandler(compat.ExecCreateHandler)).Methods(http.MethodPost)
// Added non version path to URI to support docker non versioned paths
- r.Handle("/containers/{name}/create", s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
+ r.Handle("/containers/{name}/exec", s.APIHandler(compat.ExecCreateHandler)).Methods(http.MethodPost)
// swagger:operation POST /exec/{id}/start compat startExec
// ---
// tags:
@@ -169,15 +169,15 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchExecInstance"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/exec/{id}/json"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/exec/{id}/json"), s.APIHandler(compat.ExecInspectHandler)).Methods(http.MethodGet)
// Added non version path to URI to support docker non versioned paths
- r.Handle("/exec/{id}/json", s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodGet)
+ r.Handle("/exec/{id}/json", s.APIHandler(compat.ExecInspectHandler)).Methods(http.MethodGet)
/*
libpod api follows
*/
- // swagger:operation POST /libpod/containers/{name}/create libpod libpodCreateExec
+ // swagger:operation POST /libpod/containers/{name}/exec libpod libpodCreateExec
// ---
// tags:
// - exec
@@ -243,7 +243,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// description: container is paused
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/containers/{name}/create"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/containers/{name}/exec"), s.APIHandler(compat.ExecCreateHandler)).Methods(http.MethodPost)
// swagger:operation POST /libpod/exec/{id}/start libpod libpodStartExec
// ---
// tags:
@@ -332,6 +332,6 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchExecInstance"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/exec/{id}/json"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/exec/{id}/json"), s.APIHandler(compat.ExecInspectHandler)).Methods(http.MethodGet)
return nil
}