Implement container logs handler
- Add Docker client to handlers for container operations - Implement HandleAppLogs() to fetch and return container logs - Support ?tail=N query parameter (default 500 lines) - Handle missing container gracefully
This commit is contained in:
parent
3f9d83c436
commit
daaf00893c
@ -331,6 +331,9 @@ func (h *Handlers) HandleAppDeployments() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defaultLogTail is the default number of log lines to fetch.
|
||||||
|
const defaultLogTail = "500"
|
||||||
|
|
||||||
// HandleAppLogs returns the container logs handler.
|
// HandleAppLogs returns the container logs handler.
|
||||||
func (h *Handlers) HandleAppLogs() http.HandlerFunc {
|
func (h *Handlers) HandleAppLogs() http.HandlerFunc {
|
||||||
return func(writer http.ResponseWriter, request *http.Request) {
|
return func(writer http.ResponseWriter, request *http.Request) {
|
||||||
@ -343,16 +346,37 @@ func (h *Handlers) HandleAppLogs() http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container logs fetching not yet implemented
|
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
writer.Header().Set("Content-Type", "text/plain")
|
|
||||||
|
|
||||||
if !application.ContainerID.Valid {
|
if !application.ContainerID.Valid {
|
||||||
_, _ = writer.Write([]byte("No container running"))
|
_, _ = writer.Write([]byte("No container running\n"))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = writer.Write([]byte("Container logs not implemented yet"))
|
tail := request.URL.Query().Get("tail")
|
||||||
|
if tail == "" {
|
||||||
|
tail = defaultLogTail
|
||||||
|
}
|
||||||
|
|
||||||
|
logs, logsErr := h.docker.ContainerLogs(
|
||||||
|
request.Context(),
|
||||||
|
application.ContainerID.String,
|
||||||
|
tail,
|
||||||
|
)
|
||||||
|
if logsErr != nil {
|
||||||
|
h.log.Error("failed to get container logs",
|
||||||
|
"error", logsErr,
|
||||||
|
"app", application.Name,
|
||||||
|
"container", application.ContainerID.String,
|
||||||
|
)
|
||||||
|
|
||||||
|
_, _ = writer.Write([]byte("Failed to fetch container logs\n"))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = writer.Write([]byte(logs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/upaas/internal/database"
|
"git.eeqj.de/sneak/upaas/internal/database"
|
||||||
|
"git.eeqj.de/sneak/upaas/internal/docker"
|
||||||
"git.eeqj.de/sneak/upaas/internal/globals"
|
"git.eeqj.de/sneak/upaas/internal/globals"
|
||||||
"git.eeqj.de/sneak/upaas/internal/healthcheck"
|
"git.eeqj.de/sneak/upaas/internal/healthcheck"
|
||||||
"git.eeqj.de/sneak/upaas/internal/logger"
|
"git.eeqj.de/sneak/upaas/internal/logger"
|
||||||
@ -30,6 +31,7 @@ type Params struct {
|
|||||||
App *app.Service
|
App *app.Service
|
||||||
Deploy *deploy.Service
|
Deploy *deploy.Service
|
||||||
Webhook *webhook.Service
|
Webhook *webhook.Service
|
||||||
|
Docker *docker.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handlers provides HTTP request handlers.
|
// Handlers provides HTTP request handlers.
|
||||||
@ -42,6 +44,7 @@ type Handlers struct {
|
|||||||
appService *app.Service
|
appService *app.Service
|
||||||
deploy *deploy.Service
|
deploy *deploy.Service
|
||||||
webhook *webhook.Service
|
webhook *webhook.Service
|
||||||
|
docker *docker.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Handlers instance.
|
// New creates a new Handlers instance.
|
||||||
@ -55,6 +58,7 @@ func New(_ fx.Lifecycle, params Params) (*Handlers, error) {
|
|||||||
appService: params.App,
|
appService: params.App,
|
||||||
deploy: params.Deploy,
|
deploy: params.Deploy,
|
||||||
webhook: params.Webhook,
|
webhook: params.Webhook,
|
||||||
|
docker: params.Docker,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,7 +86,7 @@ func createAppServices(
|
|||||||
logInstance *logger.Logger,
|
logInstance *logger.Logger,
|
||||||
dbInstance *database.Database,
|
dbInstance *database.Database,
|
||||||
cfg *config.Config,
|
cfg *config.Config,
|
||||||
) (*auth.Service, *app.Service, *deploy.Service, *webhook.Service) {
|
) (*auth.Service, *app.Service, *deploy.Service, *webhook.Service, *docker.Client) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
authSvc, authErr := auth.New(fx.Lifecycle(nil), auth.ServiceParams{
|
authSvc, authErr := auth.New(fx.Lifecycle(nil), auth.ServiceParams{
|
||||||
@ -128,7 +128,7 @@ func createAppServices(
|
|||||||
})
|
})
|
||||||
require.NoError(t, webhookErr)
|
require.NoError(t, webhookErr)
|
||||||
|
|
||||||
return authSvc, appSvc, deploySvc, webhookSvc
|
return authSvc, appSvc, deploySvc, webhookSvc, dockerClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupTestHandlers(t *testing.T) *testContext {
|
func setupTestHandlers(t *testing.T) *testContext {
|
||||||
@ -138,7 +138,7 @@ func setupTestHandlers(t *testing.T) *testContext {
|
|||||||
|
|
||||||
globalInstance, logInstance, dbInstance, hcInstance := createCoreServices(t, cfg)
|
globalInstance, logInstance, dbInstance, hcInstance := createCoreServices(t, cfg)
|
||||||
|
|
||||||
authSvc, appSvc, deploySvc, webhookSvc := createAppServices(
|
authSvc, appSvc, deploySvc, webhookSvc, dockerClient := createAppServices(
|
||||||
t,
|
t,
|
||||||
logInstance,
|
logInstance,
|
||||||
dbInstance,
|
dbInstance,
|
||||||
@ -156,6 +156,7 @@ func setupTestHandlers(t *testing.T) *testContext {
|
|||||||
App: appSvc,
|
App: appSvc,
|
||||||
Deploy: deploySvc,
|
Deploy: deploySvc,
|
||||||
Webhook: webhookSvc,
|
Webhook: webhookSvc,
|
||||||
|
Docker: dockerClient,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
require.NoError(t, handlerErr)
|
require.NoError(t, handlerErr)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user