Add container restart/stop/start controls

- Add HandleAppRestart, HandleAppStop, HandleAppStart handlers
- Wire up POST routes for /apps/{id}/restart, /stop, /start
- Use helper function to reduce code duplication
This commit is contained in:
Jeffrey Paul 2025-12-29 15:50:51 +07:00
parent daaf00893c
commit 8403e431d2
2 changed files with 86 additions and 0 deletions

View File

@ -380,6 +380,89 @@ func (h *Handlers) HandleAppLogs() http.HandlerFunc {
} }
} }
// containerAction represents a container operation type.
type containerAction string
const (
actionRestart containerAction = "restart"
actionStop containerAction = "stop"
actionStart containerAction = "start"
)
// handleContainerAction is a helper for container control operations.
func (h *Handlers) handleContainerAction(
writer http.ResponseWriter,
request *http.Request,
action containerAction,
) {
appID := chi.URLParam(request, "id")
application, findErr := models.FindApp(request.Context(), h.db, appID)
if findErr != nil || application == nil {
http.NotFound(writer, request)
return
}
if !application.ContainerID.Valid {
http.Redirect(writer, request, "/apps/"+appID, http.StatusSeeOther)
return
}
containerID := application.ContainerID.String
ctx := request.Context()
var actionErr error
switch action {
case actionRestart:
stopErr := h.docker.StopContainer(ctx, containerID)
if stopErr != nil {
h.log.Error("failed to stop container for restart",
"error", stopErr, "app", application.Name, "container", containerID)
}
actionErr = h.docker.StartContainer(ctx, containerID)
case actionStop:
actionErr = h.docker.StopContainer(ctx, containerID)
case actionStart:
actionErr = h.docker.StartContainer(ctx, containerID)
}
if actionErr != nil {
h.log.Error("container action failed",
"action", action, "error", actionErr,
"app", application.Name, "container", containerID)
} else {
h.log.Info("container action completed",
"action", action, "app", application.Name, "container", containerID)
}
http.Redirect(writer, request, "/apps/"+appID, http.StatusSeeOther)
}
// HandleAppRestart handles restarting an app's container.
func (h *Handlers) HandleAppRestart() http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
h.handleContainerAction(writer, request, actionRestart)
}
}
// HandleAppStop handles stopping an app's container.
func (h *Handlers) HandleAppStop() http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
h.handleContainerAction(writer, request, actionStop)
}
}
// HandleAppStart handles starting an app's container.
func (h *Handlers) HandleAppStart() http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
h.handleContainerAction(writer, request, actionStart)
}
}
// addKeyValueToApp is a helper for adding key-value pairs (env vars or labels). // addKeyValueToApp is a helper for adding key-value pairs (env vars or labels).
func (h *Handlers) addKeyValueToApp( func (h *Handlers) addKeyValueToApp(
writer http.ResponseWriter, writer http.ResponseWriter,

View File

@ -64,6 +64,9 @@ func (s *Server) SetupRoutes() {
r.Post("/apps/{id}/deploy", s.handlers.HandleAppDeploy()) r.Post("/apps/{id}/deploy", s.handlers.HandleAppDeploy())
r.Get("/apps/{id}/deployments", s.handlers.HandleAppDeployments()) r.Get("/apps/{id}/deployments", s.handlers.HandleAppDeployments())
r.Get("/apps/{id}/logs", s.handlers.HandleAppLogs()) r.Get("/apps/{id}/logs", s.handlers.HandleAppLogs())
r.Post("/apps/{id}/restart", s.handlers.HandleAppRestart())
r.Post("/apps/{id}/stop", s.handlers.HandleAppStop())
r.Post("/apps/{id}/start", s.handlers.HandleAppStart())
// Environment variables // Environment variables
r.Post("/apps/{id}/env-vars", s.handlers.HandleEnvVarAdd()) r.Post("/apps/{id}/env-vars", s.handlers.HandleEnvVarAdd())