add services with statsu server state and remove stage lights

This commit is contained in:
Adrian Zuercher
2025-09-07 14:24:38 +02:00
parent a648be3bcb
commit 9585fb1b7a
35 changed files with 2387 additions and 328 deletions

View File

@@ -0,0 +1,260 @@
package services
import (
"backend/models"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"gitea.tecamino.com/paadi/statusServer"
"github.com/gin-gonic/gin"
)
type ServicesHandler struct {
cfgDir string
cfgFile string
config models.Configuration
statusWs *statusServer.StatusWebsocket
}
func NewServicesHandler(cfgDir, cfgFile string) *ServicesHandler {
return &ServicesHandler{cfgDir: cfgDir, cfgFile: cfgFile}
}
func (s *ServicesHandler) LinkStatusServer(statusServer *statusServer.StatusWebsocket) {
s.statusWs = statusServer
}
func (s *ServicesHandler) GetAllAvaiableServices(c *gin.Context) {
var services []models.Service
defaultCfg, err := s.readDefaultConfig()
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
configFile := filepath.Join(s.cfgDir, defaultCfg.CfgFileName)
if _, err := os.Stat(configFile); err != nil {
c.JSON(http.StatusOK, gin.H{"services": defaultCfg.Services})
return
}
content, err := os.ReadFile(configFile)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
var cfg models.Configuration
err = json.Unmarshal(content, &cfg)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
// check wether service was already initiated then skip
next:
for _, new := range defaultCfg.Services {
for _, old := range cfg.Services {
if new.Name == old.Name {
continue next
}
}
services = append(services, new)
}
c.JSON(http.StatusOK, gin.H{"services": services})
}
func (s *ServicesHandler) LoadAllServices(c *gin.Context) {
defaultCfg, err := s.readDefaultConfig()
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
configFile := filepath.Join(s.cfgDir, defaultCfg.CfgFileName)
if _, err := os.Stat(configFile); err != nil {
c.JSON(http.StatusOK, gin.H{"message": "no services"})
return
}
content, err := os.ReadFile(configFile)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
err = json.Unmarshal(content, &s.config)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
if len(s.config.Services) == 0 {
c.JSON(http.StatusOK, gin.H{"message": "no services"})
return
}
c.JSON(http.StatusOK, gin.H{"services": s.config.Services})
}
func (s *ServicesHandler) AddNewService(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
var newService struct {
Name string `json:"name"`
}
err = json.Unmarshal(body, &newService)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
defaultCfg, err := s.readDefaultConfig()
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
var config models.Configuration
if _, err := os.Stat(filepath.Join(s.cfgDir, defaultCfg.CfgFileName)); err == nil {
content, err := os.ReadFile(filepath.Join(s.cfgDir, defaultCfg.CfgFileName))
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
err = json.Unmarshal(content, &config)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
}
for _, service := range defaultCfg.Services {
if service.Name == newService.Name {
config.Services = append(config.Services, service)
f, err := os.OpenFile(filepath.Join(s.cfgDir, defaultCfg.CfgFileName), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0774)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
defer f.Close()
output, err := json.Marshal(config)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
_, err = f.Write(output)
if err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
return
}
c.JSON(http.StatusOK, gin.H{"message": "service '" + newService.Name + "' added"})
return
}
}
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(errors.New("no service '"+newService.Name+"' found")))
}
func (s *ServicesHandler) StartService(c *gin.Context) {
service := c.Param("service")
s.statusWs.Publish("status/"+service, gin.H{
"state": "Starting",
})
for i := range s.config.Services {
if s.config.Services[i].Name == service {
if err := s.config.Services[i].Start(func(e string) {
s.statusWs.Publish("status/"+service, gin.H{"state": "Error", "message": e})
}); err != nil {
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err))
s.statusWs.Publish("status/"+service, gin.H{
"state": "Error",
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("service '%s' started", service),
})
s.statusWs.Publish("status/"+service, gin.H{
"state": "Started",
})
return
}
}
c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse(fmt.Sprintf("no service '%s' found", service)))
s.statusWs.Publish("status/"+service, gin.H{
"state": "Error",
"message": fmt.Sprintf("no service '%s' found", service),
})
}
func (s *ServicesHandler) StopService(c *gin.Context) {
service := c.Param("service")
s.statusWs.Publish("status/"+service, gin.H{
"state": "Stopping",
})
for i := range s.config.Services {
if s.config.Services[i].Name == service {
if err := s.config.Services[i].Stop(); err != nil {
c.JSON(http.StatusBadGateway, gin.H{
"error": true,
"message": fmt.Sprintf("service '%s' error; %v", service, err),
})
s.statusWs.Publish("status/"+service, gin.H{
"state": "Error",
"message": fmt.Sprintf("service '%s' error; %v", service, err),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("service '%s' stopped", service),
})
s.statusWs.Publish("status/"+service, gin.H{
"state": "Stopped",
})
return
}
}
c.JSON(http.StatusBadRequest, gin.H{
"error": true,
"message": fmt.Sprintf("no service '%s' found", service),
})
s.statusWs.Publish("status/"+service, gin.H{
"state": "Stopped",
"message": fmt.Sprintf("no service '%s' found", service),
})
}
func (s *ServicesHandler) readDefaultConfig() (data models.Configuration, err error) {
content, err := os.ReadFile(filepath.Join(s.cfgDir, s.cfgFile))
if err != nil {
return
}
err = json.Unmarshal(content, &data)
return
}