diff --git a/internal/api/handler.go b/internal/api/handler.go index 234cffa3..a473b15b 100644 --- a/internal/api/handler.go +++ b/internal/api/handler.go @@ -122,7 +122,7 @@ func NewHandler() *gin.Engine { { docker.GET("/containers", dockerApi.Containers) docker.GET("/info", dockerApi.Info) - docker.GET("/logs/:server/:container", dockerApi.Logs) + docker.GET("/logs/:id", dockerApi.Logs) } } diff --git a/internal/api/v1/docker/logs.go b/internal/api/v1/docker/logs.go index bfa392c3..42283364 100644 --- a/internal/api/v1/docker/logs.go +++ b/internal/api/v1/docker/logs.go @@ -3,6 +3,7 @@ package dockerapi import ( "context" "errors" + "fmt" "net/http" "github.com/docker/docker/api/types/container" @@ -10,15 +11,11 @@ import ( "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" apitypes "github.com/yusing/go-proxy/internal/api/types" + "github.com/yusing/go-proxy/internal/docker" "github.com/yusing/go-proxy/internal/net/gphttp/websocket" "github.com/yusing/go-proxy/internal/task" ) -type LogsPathParams struct { - Server string `uri:"server" binding:"required"` - ContainerID string `uri:"container" binding:"required"` -} // @name LogsPathParams - type LogsQueryParams struct { Stdout bool `form:"stdout,default=true"` Stderr bool `form:"stderr,default=true"` @@ -30,12 +27,11 @@ type LogsQueryParams struct { // @x-id "logs" // @BasePath /api/v1 // @Summary Get docker container logs -// @Description Get docker container logs +// @Description Get docker container logs by container id // @Tags docker,websocket // @Accept json // @Produce json -// @Param server path string true "server name" -// @Param container path string true "container id" +// @Param id path string true "container id" // @Param stdout query bool false "show stdout" // @Param stderr query bool false "show stderr" // @Param from query string false "from timestamp" @@ -44,31 +40,40 @@ type LogsQueryParams struct { // @Success 200 // @Failure 400 {object} apitypes.ErrorResponse // @Failure 403 {object} apitypes.ErrorResponse -// @Failure 404 {object} apitypes.ErrorResponse +// @Failure 404 {object} apitypes.ErrorResponse "server not found or container not found" // @Failure 500 {object} apitypes.ErrorResponse -// @Router /docker/logs/{server}/{container} [get] +// @Router /docker/logs/{id} [get] func Logs(c *gin.Context) { - var pathParams LogsPathParams + id := c.Param("id") + if id == "" { + c.JSON(http.StatusBadRequest, apitypes.Error("container id is required")) + return + } + var queryParams LogsQueryParams if err := c.ShouldBindQuery(&queryParams); err != nil { c.JSON(http.StatusBadRequest, apitypes.Error("invalid query params")) return } - if err := c.ShouldBindUri(&pathParams); err != nil { - c.JSON(http.StatusBadRequest, apitypes.Error("invalid path params")) + + // TODO: implement levels + dockerHost, ok := docker.GetDockerHostByContainerID(id) + if !ok { + c.JSON(http.StatusNotFound, apitypes.Error(fmt.Sprintf("container %s not found in %s", id, c.GetString("server")))) return } - // TODO: implement levels - dockerClient, found, err := getDockerClient(pathParams.Server) + dockerClient, found, err := getDockerClient(dockerHost) if err != nil { c.Error(apitypes.InternalServerError(err, "failed to get docker client")) return } + if !found { c.JSON(http.StatusNotFound, apitypes.Error("server not found")) return } + defer dockerClient.Close() opts := container.LogsOptions{ @@ -84,7 +89,7 @@ func Logs(c *gin.Context) { opts.Details = true } - logs, err := dockerClient.ContainerLogs(c.Request.Context(), pathParams.ContainerID, opts) + logs, err := dockerClient.ContainerLogs(c.Request.Context(), id, opts) if err != nil { c.Error(apitypes.InternalServerError(err, "failed to get container logs")) return @@ -106,8 +111,8 @@ func Logs(c *gin.Context) { return } log.Err(err). - Str("server", pathParams.Server). - Str("container", pathParams.ContainerID). + Str("server", dockerHost). + Str("container", id). Msg("failed to de-multiplex logs") } }