package controllers import ( "context" "lokistack/dto" "lokistack/models" "lokistack/services" "lokistack/utils" "time" "github.com/gin-gonic/gin" ) type DeploymentController struct { service *services.DeploymentService } func NewDeploymentController() *DeploymentController { return &DeploymentController{service: services.NewDeploymentService()} } func (ctrl *DeploymentController) Create(c *gin.Context) { var req dto.CreateDeploymentRequest if !utils.BindAndValidate(c, &req) { return } deployment, err := ctrl.service.Create(&services.CreateDeploymentRequest{ Name: req.Name, Description: req.Description, Version: req.Version, Mode: req.Mode, ClusterID: req.ClusterID, HostID: req.HostID, ListenIP: req.ListenIP, ListenPort: req.ListenPort, Namespace: req.Namespace, StorageConfigID: req.StorageConfigID, AuthEnabled: req.AuthEnabled, RetentionDays: req.RetentionDays, Replicas: req.Replicas, ResourcesCPU: req.ResourcesCPU, ResourcesMem: req.ResourcesMem, StorageSize: req.StorageSize, GrafanaEnabled: req.GrafanaEnabled, GrafanaVersion: req.GrafanaVersion, }) if err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, models.SanitizedJSON(deployment)) } func (ctrl *DeploymentController) Get(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } deployment, err := ctrl.service.Get(uint(id)) if err != nil { utils.NotFound(c, "部署不存在") return } utils.Success(c, models.SanitizedJSON(deployment)) } // Ready 部署就绪探测(经自动注册的数据源访问 Loki /ready) func (ctrl *DeploymentController) Ready(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } d, err := ctrl.service.Get(uint(id)) if err != nil { utils.NotFound(c, "部署不存在") return } ctx, cancel := context.WithTimeout(c.Request.Context(), 15*time.Second) defer cancel() ready, msg := services.DeploymentReady(ctx, d.Name) utils.Success(c, gin.H{"ready": ready, "message": msg}) } // Preflight 向导预检:聚合存储/集群/主机/Loki/采集器状态 func (ctrl *DeploymentController) Preflight(c *gin.Context) { utils.Success(c, ctrl.service.Preflight()) } // GetVersions 返回支持的 Loki 版本列表(前端部署表单版本下拉数据源) func (ctrl *DeploymentController) GetVersions(c *gin.Context) { utils.Success(c, gin.H{"versions": services.LokiVersionList}) } func (ctrl *DeploymentController) List(c *gin.Context) { page, pageSize := utils.Pagination(c) deployments, total, err := ctrl.service.List(page, pageSize) if err != nil { utils.Error(c, 500, err.Error()) return } utils.Success(c, utils.PageData{ List: models.SanitizedJSON(deployments), Total: total, Page: page, PageSize: pageSize, }) } func (ctrl *DeploymentController) Update(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } var updates map[string]interface{} if !utils.BindAndValidate(c, &updates) { return } if err := ctrl.service.Update(uint(id), updates); err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"message": "updated"}) } // UpdateRetention 校验 YAML 片段,保存部署配置,并可立即重部署。 func (ctrl *DeploymentController) UpdateRetention(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } var req dto.UpdateRetentionRequest if !utils.BindAndValidate(c, &req) { return } days, err := ctrl.service.UpdateRetention(uint(id), req.YAML, req.Apply) if err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"retentionDays": days, "applying": req.Apply}) } // GetLiveConfig 返回运行中的完整 Loki YAML,服务层会先遮盖凭证。 func (ctrl *DeploymentController) GetLiveConfig(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } ctx, cancel := context.WithTimeout(c.Request.Context(), 15*time.Second) defer cancel() result, err := ctrl.service.GetLiveConfig(ctx, uint(id)) if err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, result) } func (ctrl *DeploymentController) Delete(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } if err := ctrl.service.Delete(uint(id)); err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"message": "deleted"}) } func (ctrl *DeploymentController) Deploy(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } if err := ctrl.service.StartDeploy(uint(id)); err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"message": "deployment started"}) } func (ctrl *DeploymentController) Stop(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } if err := ctrl.service.StopDeployment(uint(id)); err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"message": "deployment stopped"}) } func (ctrl *DeploymentController) Restart(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } if err := ctrl.service.RestartDeployment(uint(id)); err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"message": "deployment restarted"}) } // GetUsage 返回 Loki 实例的资源用量(CPU/内存/限流),供页面判断是否需要扩容。 func (ctrl *DeploymentController) GetUsage(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } usage, err := ctrl.service.GetUsage(uint(id)) if err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, usage) } func (ctrl *DeploymentController) GetLogs(c *gin.Context) { id, err := utils.IntParam(c, "id") if err != nil { utils.BadRequest(c, "ID 无效") return } page, pageSize := utils.Pagination(c) logs, total, err := ctrl.service.GetLogs(uint(id), page, pageSize) if err != nil { utils.Error(c, 500, err.Error()) return } utils.Success(c, utils.PageData{ List: logs, Total: total, Page: page, PageSize: pageSize, }) } func (ctrl *DeploymentController) GetStats(c *gin.Context) { stats, err := ctrl.service.GetStats() if err != nil { utils.Error(c, 500, err.Error()) return } utils.Success(c, stats) }