From 8b1f7ce3d08386cbd4f20cdc13ca9c4119f9a766 Mon Sep 17 00:00:00 2001 From: Vincent van Dam Date: Tue, 16 May 2023 19:59:34 +0200 Subject: [PATCH] Add podman exec support --- .../server/routes/{docker => common}/exec.go | 17 +++++++++++------ internal/server/routes/common/types.go | 19 +++++++++++++++++++ internal/server/routes/docker.go | 6 +++--- internal/server/routes/docker/types.go | 18 ------------------ internal/server/routes/libpod.go | 4 ++++ 5 files changed, 37 insertions(+), 27 deletions(-) rename internal/server/routes/{docker => common}/exec.go (82%) create mode 100644 internal/server/routes/common/types.go diff --git a/internal/server/routes/docker/exec.go b/internal/server/routes/common/exec.go similarity index 82% rename from internal/server/routes/docker/exec.go rename to internal/server/routes/common/exec.go index 81a9a13..589f3b0 100644 --- a/internal/server/routes/docker/exec.go +++ b/internal/server/routes/common/exec.go @@ -1,4 +1,4 @@ -package docker +package common import ( "encoding/json" @@ -10,20 +10,21 @@ import ( "github.com/joyrex2001/kubedock/internal/model/types" "github.com/joyrex2001/kubedock/internal/server/httputil" - "github.com/joyrex2001/kubedock/internal/server/routes/common" ) // ContainerExec - create an exec instance. // https://docs.docker.com/engine/api/v1.41/#operation/ContainerInspect +// https://docs.podman.io/en/latest/_static/api.html?version=v4.2#tag/exec/operation/ContainerExecLibpod // POST "/containers/:id/exec" -func ContainerExec(cr *common.ContextRouter, c *gin.Context) { +// POST "/libpod/containers/:id/exec" +func ContainerExec(cr *ContextRouter, c *gin.Context) { in := &ContainerExecRequest{} if err := json.NewDecoder(c.Request.Body).Decode(&in); err != nil { httputil.Error(c, http.StatusInternalServerError, err) return } - if in.Env != nil { + if in.Env != nil && len(in.Env) > 0 { httputil.Error(c, http.StatusBadRequest, fmt.Errorf("env variables not supported")) return } @@ -63,8 +64,10 @@ func ContainerExec(cr *common.ContextRouter, c *gin.Context) { // ExecStart - start an exec instance. // https://docs.docker.com/engine/api/v1.41/#operation/ExecStart +// https://docs.podman.io/en/latest/_static/api.html?version=v4.2#tag/exec/operation/ExecStartLibpod // POST "/exec/:id/start" -func ExecStart(cr *common.ContextRouter, c *gin.Context) { +// POST "/libpod/exec/:id/start" +func ExecStart(cr *ContextRouter, c *gin.Context) { req := &ExecStartRequest{} if err := json.NewDecoder(c.Request.Body).Decode(&req); err != nil { httputil.Error(c, http.StatusInternalServerError, err) @@ -115,8 +118,10 @@ func ExecStart(cr *common.ContextRouter, c *gin.Context) { // ExecInfo - return low-level information about an exec instance. // https://docs.docker.com/engine/api/v1.41/#operation/ExecInspect +// https://docs.podman.io/en/latest/_static/api.html?version=v4.2#tag/exec/operation/ExecInspectLibpod // GET "/exec/:id/json" -func ExecInfo(cr *common.ContextRouter, c *gin.Context) { +// GET "/libpod/exec/:id/json" +func ExecInfo(cr *ContextRouter, c *gin.Context) { id := c.Param("id") exec, err := cr.DB.GetExec(id) if err != nil { diff --git a/internal/server/routes/common/types.go b/internal/server/routes/common/types.go new file mode 100644 index 0000000..4d53303 --- /dev/null +++ b/internal/server/routes/common/types.go @@ -0,0 +1,19 @@ +package common + +// ContainerExecRequest represents the json structure that +// is used for the /conteiner/:id/exec request. +type ContainerExecRequest struct { + Cmd []string `json:"Cmd"` + Stdin bool `json:"AttachStdin"` + Stdout bool `json:"AttachStdout"` + Stderr bool `json:"AttachStderr"` + Tty bool `json:"Tty"` + Env []string `json:"Env"` +} + +// ExecStartRequest represents the json structure that is +// used for the /exec/:id/start request. +type ExecStartRequest struct { + Detach bool `json:"Detach"` + Tty bool `json:"Tty"` +} diff --git a/internal/server/routes/docker.go b/internal/server/routes/docker.go index ac95ada..af0ddae 100644 --- a/internal/server/routes/docker.go +++ b/internal/server/routes/docker.go @@ -25,7 +25,6 @@ func RegisterDockerRoutes(router *gin.Engine, cr *common.ContextRouter) { router.POST("/containers/create", wrap(docker.ContainerCreate)) router.POST("/containers/:id/start", wrap(common.ContainerStart)) router.POST("/containers/:id/attach", wrap(common.ContainerAttach)) - router.POST("/containers/:id/exec", wrap(docker.ContainerExec)) router.POST("/containers/:id/stop", wrap(common.ContainerStop)) router.POST("/containers/:id/restart", wrap(common.ContainerRestart)) router.POST("/containers/:id/kill", wrap(common.ContainerKill)) @@ -40,8 +39,9 @@ func RegisterDockerRoutes(router *gin.Engine, cr *common.ContextRouter) { router.PUT("/containers/:id/archive", wrap(docker.PutArchive)) router.POST("/containers/:id/rename", wrap(docker.ContainerRename)) - router.POST("/exec/:id/start", wrap(docker.ExecStart)) - router.GET("/exec/:id/json", wrap(docker.ExecInfo)) + router.POST("/containers/:id/exec", wrap(common.ContainerExec)) + router.POST("/exec/:id/start", wrap(common.ExecStart)) + router.GET("/exec/:id/json", wrap(common.ExecInfo)) router.POST("/networks/create", wrap(docker.NetworksCreate)) router.POST("/networks/:id/connect", wrap(docker.NetworksConnect)) diff --git a/internal/server/routes/docker/types.go b/internal/server/routes/docker/types.go index 93211ea..a3f02b0 100644 --- a/internal/server/routes/docker/types.go +++ b/internal/server/routes/docker/types.go @@ -15,24 +15,6 @@ type ContainerCreateRequest struct { NetworkConfig NetworkingConfig `json:"NetworkingConfig"` } -// ContainerExecRequest represents the json structure that -// is used for the /conteiner/:id/exec request. -type ContainerExecRequest struct { - Cmd []string `json:"Cmd"` - Stdin bool `json:"AttachStdin"` - Stdout bool `json:"AttachStdout"` - Stderr bool `json:"AttachStderr"` - Tty bool `json:"Tty"` - Env []string `json:"Env"` -} - -// ExecStartRequest represents the json structure that is -// used for the /exec/:id/start request. -type ExecStartRequest struct { - Detach bool `json:"Detach"` - Tty bool `json:"Tty"` -} - // NetworkCreateRequest represents the json structure that // is used for the /networks/create post endpoint. type NetworkCreateRequest struct { diff --git a/internal/server/routes/libpod.go b/internal/server/routes/libpod.go index 2b6e8aa..e05f510 100644 --- a/internal/server/routes/libpod.go +++ b/internal/server/routes/libpod.go @@ -38,6 +38,10 @@ func RegisterLibpodRoutes(router *gin.Engine, cr *common.ContextRouter) { router.GET("/libpod/containers/:id/logs", wrap(common.ContainerLogs)) router.POST("/libpod/containers/:id/rename", wrap(common.ContainerRename)) + router.POST("/libpod/containers/:id/exec", wrap(common.ContainerExec)) + router.POST("/libpod/exec/:id/start", wrap(common.ExecStart)) + router.GET("/libpod/exec/:id/json", wrap(common.ExecInfo)) + // not supported podman api at the moment router.GET("/libpod/info", httputil.NotImplemented) router.POST("/libpod/images/build", httputil.NotImplemented)