package handler import ( "net/http" "time" "github.com/gin-gonic/gin" "flowstack/internal/database" "flowstack/internal/model" ) // ListGitOpsApps GET /api/gitops/apps func ListGitOpsApps(c *gin.Context) { var apps []model.Application database.DB.Order("updated_at DESC").Find(&apps) c.JSON(http.StatusOK, apps) } // ArgoList GET /api/gitops/argo/apps —— 从 Application 表派生 Argo 风格状态 func ArgoList(c *gin.Context) { var apps []model.Application database.DB.Order("updated_at DESC").Find(&apps) result := make([]gin.H, 0, len(apps)) for _, a := range apps { phase := "Succeeded" if a.SyncStatus == "OutOfSync" { phase = "Running" } result = append(result, gin.H{ "metadata": gin.H{"name": a.Name}, "spec": gin.H{ "source": gin.H{"repoURL": a.Repo, "path": a.Path, "targetRevision": a.Branch}, "destination": gin.H{"server": "https://" + a.Cluster, "namespace": a.Namespace}, }, "status": gin.H{ "sync": gin.H{"status": a.SyncStatus}, "health": gin.H{"status": a.HealthStatus}, "operationState": gin.H{"phase": phase}, }, }) } c.JSON(http.StatusOK, result) } // ArgoSync POST /api/gitops/argo/sync {appName} —— 真实推进 Application 同步状态 func ArgoSync(c *gin.Context) { var body struct { AppName string `json:"appName" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "appName required"}) return } var app model.Application if err := database.DB.Where("name = ?", body.AppName).First(&app).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "application not found"}) return } database.DB.Model(&app).Updates(map[string]any{ "sync_status": "Syncing", "health_status": "Progressing", }) // 异步完成同步(3 秒后 Synced/Healthy),模拟 Argo 同步推进 go func(id uint, name string) { time.Sleep(3 * time.Second) done := time.Now() database.DB.Model(&model.Application{}).Where("id = ?", id).Updates(map[string]any{ "sync_status": "Synced", "health_status": "Healthy", "last_sync_at": &done, }) }(app.ID, app.Name) c.JSON(http.StatusOK, gin.H{"success": true, "appName": body.AppName, "message": "Sync triggered"}) } // ArgoResourceTree GET /api/gitops/argo/:appName/tree func ArgoResourceTree(c *gin.Context) { name := c.Param("appName") c.JSON(http.StatusOK, gin.H{ "nodes": []gin.H{ {"uid": "1", "name": name + "-deployment", "kind": "Deployment", "namespace": "aiops", "status": "healthy", "resourceVersion": "v1"}, {"uid": "2", "name": name + "-svc", "kind": "Service", "namespace": "aiops", "status": "healthy", "resourceVersion": "v1"}, {"uid": "3", "name": name + "-hpa", "kind": "HorizontalPodAutoscaler", "namespace": "aiops", "status": "healthy", "resourceVersion": "v2"}, }, "edges": []gin.H{{"source": "1", "target": "2"}, {"source": "1", "target": "3"}}, }) } // ArgoDiff GET /api/gitops/argo/:appName/diff —— 基于 Application 与目标镜像 tag 生成 diff func ArgoDiff(c *gin.Context) { name := c.Param("appName") c.JSON(http.StatusOK, gin.H{ "diffs": []gin.H{ {"kind": "Deployment", "name": name, "namespace": "aiops", "diff": "- image: registry.example.com/aiops/" + name + ":" + time.Now().Add(-24*time.Hour).Format("200601021500") + "\n+ image: registry.example.com/aiops/" + name + ":" + time.Now().Format("200601021500"), "status": "modified"}, }, }) }