Files
flux/internal/handlers/app.go
2025-05-15 18:33:02 +00:00

237 lines
6.2 KiB
Go

package handlers
import (
"encoding/json"
"net/http"
"github.com/google/uuid"
proxyManagerService "github.com/juls0730/flux/internal/services/proxy"
"github.com/juls0730/flux/pkg/API"
"github.com/juls0730/sentinel"
"go.uber.org/zap"
)
func (flux *FluxServer) GetAllApps(w http.ResponseWriter, r *http.Request) {
var apps []API.App
for _, app := range flux.appManager.GetAllApps() {
var extApp API.App
deploymentStatus, err := app.Deployment.Status(r.Context(), flux.docker, flux.logger)
if err != nil {
flux.logger.Errorw("Failed to get deployment status", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
extApp.Id = app.Id
extApp.Name = app.Name
extApp.DeploymentID = app.DeploymentID
extApp.DeploymentStatus = deploymentStatus
apps = append(apps, extApp)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(apps)
}
func (flux *FluxServer) GetAppById(w http.ResponseWriter, r *http.Request) {
id, err := uuid.Parse(r.PathValue("id"))
if err != nil {
http.Error(w, "Invalid app id", http.StatusBadRequest)
return
}
app := flux.appManager.GetApp(id)
if app == nil {
http.Error(w, "App not found", http.StatusNotFound)
return
}
var extApp API.App
deploymentStatus, err := app.Deployment.Status(r.Context(), flux.docker, flux.logger)
if err != nil {
flux.logger.Errorw("Failed to get deployment status", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
extApp.Id = app.Id
extApp.Name = app.Name
extApp.DeploymentID = app.DeploymentID
extApp.DeploymentStatus = deploymentStatus
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(extApp)
}
func (flux *FluxServer) GetAppByName(w http.ResponseWriter, r *http.Request) {
name := r.PathValue("name")
app := flux.appManager.GetAppByName(name)
if app == nil {
http.Error(w, "App not found", http.StatusNotFound)
return
}
var extApp API.App
deploymentStatus, err := app.Deployment.Status(r.Context(), flux.docker, flux.logger)
if err != nil {
flux.logger.Errorw("Failed to get deployment status", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
extApp.Id = app.Id
extApp.Name = app.Name
extApp.DeploymentID = app.DeploymentID
extApp.DeploymentStatus = deploymentStatus
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(extApp)
}
func (flux *FluxServer) StartApp(w http.ResponseWriter, r *http.Request) {
id, err := uuid.Parse(r.PathValue("id"))
if err != nil {
http.Error(w, "Invalid app id", http.StatusBadRequest)
return
}
app := flux.appManager.GetApp(id)
if app == nil {
http.Error(w, "App not found", http.StatusNotFound)
return
}
status, err := app.Deployment.Status(r.Context(), flux.docker, flux.logger)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if status == "running" {
http.Error(w, "App is already running", http.StatusNotModified)
return
}
app.State = "running"
_, err = flux.db.ExecContext(r.Context(), "UPDATE apps SET state = ? WHERE id = ?", app.State, app.Id[:])
if err != nil {
flux.logger.Errorw("Failed to update app state", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = app.Deployment.Start(r.Context(), flux.docker)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
deploymentInternalUrl, err := app.Deployment.GetInternalUrl(flux.docker)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
newProxy, err := sentinel.NewDeploymentProxy(deploymentInternalUrl.String(), proxyManagerService.GetTransport)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
flux.proxy.AddProxy(app.Deployment.URL, newProxy)
w.WriteHeader(http.StatusOK)
}
func (flux *FluxServer) StopApp(w http.ResponseWriter, r *http.Request) {
id, err := uuid.Parse(r.PathValue("id"))
if err != nil {
http.Error(w, "Invalid app id", http.StatusBadRequest)
return
}
app := flux.appManager.GetApp(id)
if app == nil {
http.Error(w, "App not found", http.StatusNotFound)
return
}
status, err := app.Deployment.Status(r.Context(), flux.docker, flux.logger)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if status == "stopped" || status == "failed" {
http.Error(w, "App is already stopped", http.StatusNotModified)
return
}
app.State = "stopped"
_, err = flux.db.ExecContext(r.Context(), "UPDATE apps SET state = ? WHERE id = ?", app.State, app.Id[:])
if err != nil {
flux.logger.Errorw("Failed to update app state", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = app.Deployment.Stop(r.Context(), flux.docker)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
flux.proxy.RemoveDeployment(app.Deployment.URL)
w.WriteHeader(http.StatusOK)
}
func (flux *FluxServer) DeleteAllDeploymentsHandler(w http.ResponseWriter, r *http.Request) {
if flux.config.DisableDeleteAll {
http.Error(w, "Delete all deployments is disabled", http.StatusForbidden)
return
}
apps := flux.appManager.GetAllApps()
for _, app := range apps {
err := flux.appManager.DeleteApp(app.Id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
w.WriteHeader(http.StatusOK)
}
func (flux *FluxServer) DeleteDeployHandler(w http.ResponseWriter, r *http.Request) {
id, err := uuid.Parse(r.PathValue("id"))
if err != nil {
http.Error(w, "Invalid app id", http.StatusBadRequest)
return
}
app := flux.appManager.GetApp(id)
if app == nil {
http.Error(w, "App not found", http.StatusNotFound)
return
}
status, err := app.Deployment.Status(r.Context(), flux.docker, flux.logger)
if err != nil {
flux.logger.Errorw("Failed to get deployment status", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if status != "stopped" {
app.Deployment.Stop(r.Context(), flux.docker)
flux.proxy.RemoveDeployment(app.Deployment.URL)
}
err = flux.appManager.DeleteApp(id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}