package router import ( "ezops/config" "ezops/controller" "ezops/middleware" "ezops/model" ezredis "ezops/pkg/redis" "ezops/pkg/siteprobe" "ezops/pkg/systask" "ezops/pkg/toolinstaller" "ezops/pkg/wshub" "ezops/service" "strconv" "github.com/gin-gonic/gin" "go.uber.org/zap" "gorm.io/gorm" "time" ) // Register 注册所有路由 // Logan.Li // cache 参数为可选 Redis 缓存实例(支持 redka/redis 双后端) func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, cache interface{}) { // 提取 Redis 缓存实例(供流水线 WebSocket 等使用) redisCache, _ := cache.(ezredis.Cache) // API版本前缀 api := r.Group("/api/v1") // 健康检查 r.GET("/health", func(c *gin.Context) { c.JSON(200, gin.H{"status": "ok"}) }) // Agent 二进制下载 + 一键安装脚本(无需鉴权,方便 curl|bash) registerAgentDownloads(r, log) // === A3: 统一 WebSocket 连接管理器 === // Logan.Li // 所有 WebSocket handler 共享同一个 WSManager(心跳、连接注册、监控、优雅关闭) wsMgr := wshub.New(wshub.DefaultConfig()) // WebSocket终端 (JWT 鉴权,支持 ?token= 查询参数;终端会话录制) // Logan.Li auditHub := controller.NewAuditHub(wsMgr) webShellHandler := controller.NewWebShellHandler(db, auditHub, wsMgr) r.GET("/ws/terminal", middleware.JWTAuth(&cfg.JWT, db), webShellHandler.Terminal) rdpHandler := controller.NewRDPHandler(db, cfg.JWT.Secret, wsMgr) r.GET("/ws/rdp", middleware.JWTAuth(&cfg.JWT, db), rdpHandler.Serve) r.GET("/ws/rdp-audit/:sessionId", middleware.JWTAuth(&cfg.JWT, db), rdpHandler.ServeLive) // WebSocket 审计实时流 — 在线会话实时查看 // Logan.Li r.GET("/ws/audit/:sessionId", middleware.JWTAuth(&cfg.JWT, db), func(c *gin.Context) { idStr := c.Param("sessionId") id, err := strconv.ParseUint(idStr, 10, 64) if err != nil { c.JSON(400, gin.H{"error": "invalid session id"}) return } var session model.TerminalSession if err := db.First(&session, id).Error; err != nil { c.JSON(404, gin.H{"error": "session not found"}) return } auditHub.ServeAuditStream(c, uint(id), session.RecordData, gin.H{ "session_id": session.ID, "username": session.Username, "server_name": session.ServerName, "server_ip": session.ServerIP, "start_time": session.StartTime, "status": session.Status, }) }) // WebSocket 实时指标推送(JWT 鉴权) // Logan.Li metricsHub := controller.NewMetricsHub() metricsWSHandler := controller.NewMetricsWSHandler(metricsHub, wsMgr) r.GET("/ws/metrics", middleware.JWTAuth(&cfg.JWT, db), metricsWSHandler.ServeWS) // 流水线运行日志与工作区属于构建产物,必须同时完成登录和所属流水线授权。 // Logan.Li wsLogHandler := controller.NewWSPipelineLogHandler(db, redisCache, wsMgr) r.GET("/ws/pipeline/:runId/log", middleware.JWTAuth(&cfg.JWT, db), middleware.PipelineRunAccess(db), wsLogHandler.StreamLog) r.GET("/api/v1/pipelines/runs/:runId/log-stream", middleware.JWTAuth(&cfg.JWT, db), middleware.PipelineRunAccess(db), wsLogHandler.GetLogHistory) // 工作区文件浏览器(浏览/下载流水线构建目录文件) workspaceFilesHandler := controller.NewWorkspaceFilesHandler(db) r.GET("/api/v1/pipelines/runs/:runId/files", middleware.JWTAuth(&cfg.JWT, db), middleware.PipelineRunAccess(db), workspaceFilesHandler.ListFiles) r.GET("/api/v1/pipelines/runs/:runId/files/download", middleware.JWTAuth(&cfg.JWT, db), middleware.PipelineRunAccess(db), workspaceFilesHandler.DownloadFile) // WebSocket K8s exec 交互终端 // Logan.Li k8sHandler := controller.NewKubernetesHandler(db, wsMgr) r.GET("/ws/kubernetes-exec/:id/namespaces/:namespace/pods/:podName", middleware.JWTAuth(&cfg.JWT, db), k8sHandler.ExecTerminal) // ToolInstaller(工具懒加载服务 — kubectl/maven/node/helm)// Logan.Li ti := toolinstaller.New(db) // V2 Services 层 — 依赖注入 (server, credential, alert) // Logan.Li svcs := service.NewServices(db, redisCache, cfg.JWT.Secret) // WebSocket kubectl 命令行终端 // Logan.Li kubectlShellHandler := controller.NewKubectlShellHandler(db, ti, wsMgr) r.GET("/ws/kubectl", middleware.JWTAuth(&cfg.JWT, db), kubectlShellHandler.Terminal) // === A3: WebSocket 连接监控端点 === // Logan.Li wsAPI := api.Group("/ws", middleware.JWTAuth(&cfg.JWT, db)) { // GET /api/v1/ws/connections — 列出所有活跃 WS 连接 wsAPI.GET("/connections", func(c *gin.Context) { connections := wsMgr.ListConnections() c.JSON(200, gin.H{ "code": 200, "data": connections, }) }) // GET /api/v1/ws/stats — 聚合统计(总数 + 按类型/用户分布) wsAPI.GET("/stats", func(c *gin.Context) { c.JSON(200, gin.H{ "code": 200, "data": wsMgr.GetStats(), }) }) } // 公开路由 authHandler := controller.NewUserHandler(db, cfg) api.POST("/auth/login", authHandler.Login) api.POST("/auth/register", authHandler.Register) // RDPDR Download 捕获文件拉取(token 鉴权)。// Logan.Li api.GET("/rdp-staged/:token", controller.ServeRDPStaged) // Webhook 触发路由(无需 JWT,由 Webhook Token 签名验证) pipelineHandler := controller.NewPipelineHandler(db, redisCache, ti, cfg.JWT.Secret) webhookGroup := api.Group("/webhook") { webhookGroup.POST("/job/:jobName", pipelineHandler.WebhookTrigger) webhookGroup.POST("/pipeline/:code", pipelineHandler.WebhookTrigger) } // Agent 安装处理器(在 servers 和 agent 路由中共享) agentInstallHandler := controller.NewAgentInstallHandler(db) // 需要认证的路由 authorized := api.Group("") authorized.Use(middleware.JWTAuth(&cfg.JWT, db)) // 用户路由 user := authorized.Group("/user") { user.GET("/profile", authHandler.GetProfile) user.GET("/permissions", authHandler.GetMyPermissions) user.PUT("/profile", authHandler.UpdateProfile) user.POST("/change-password", authHandler.ChangePassword) user.PUT("/password", authHandler.ChangePassword) // 兼容前端 // Logan.Li user.GET("/roles", authHandler.ListRoles) user.GET("/api-access-key", authHandler.GetApiAccessKey) user.PUT("/api-access-key", authHandler.UpdateApiAccessKey) user.POST("/api-access-key/regenerate", authHandler.RegenerateApiAccessKey) user.POST("/api-access-key/extend", authHandler.ExtendApiAccessKey) user.DELETE("/api-access-key", authHandler.RevokeApiAccessKey) } // 管理员路由 admin := authorized.Group("/admin") admin.Use(middleware.AdminAuth()) { admin.GET("/users", authHandler.ListUsers) admin.GET("/users/:id", authHandler.GetUser) admin.POST("/users", authHandler.CreateUser) admin.PUT("/users/:id", authHandler.UpdateUser) admin.DELETE("/users/:id", authHandler.DeleteUser) admin.POST("/users/batch-delete", authHandler.BatchDeleteUsers) // Logan.Li admin.POST("/users/:id/reset-password", authHandler.ResetUserPassword) admin.POST("/users/batch-import", authHandler.BatchImportUsers) admin.GET("/users/import-template", authHandler.ImportTemplate) // 角色管理路由 // Logan.Li admin.GET("/roles", authHandler.ListRoles) admin.POST("/roles", authHandler.CreateRole) admin.PUT("/roles/:id", authHandler.UpdateRole) admin.DELETE("/roles/:id", authHandler.DeleteRole) // 权限列表(供角色权限选择) admin.GET("/permissions", authHandler.ListPermissions) // Item Role 管理(Jenkins-style regex pipeline matching) // Logan.Li itemRoleHandler := controller.NewItemRoleHandler(db) admin.GET("/item-roles", itemRoleHandler.ListItemRoles) admin.POST("/item-roles", itemRoleHandler.CreateItemRole) admin.PUT("/item-roles/:id", itemRoleHandler.UpdateItemRole) admin.DELETE("/item-roles/:id", itemRoleHandler.DeleteItemRole) admin.GET("/users/:id/item-roles", itemRoleHandler.ListUserItemRoles) admin.POST("/users/:id/item-roles", itemRoleHandler.AssignItemRole) admin.DELETE("/users/:id/item-roles/:roleId", itemRoleHandler.RemoveItemRole) // 日志查询范围权限(正则匹配 ES 索引 / Loki Label)// Logan.Li logScopeRoleHandler := controller.NewLogScopeRoleHandler(db) admin.GET("/log-scope-roles", logScopeRoleHandler.ListLogScopeRoles) admin.POST("/log-scope-roles", logScopeRoleHandler.CreateLogScopeRole) admin.PUT("/log-scope-roles/:id", logScopeRoleHandler.UpdateLogScopeRole) admin.DELETE("/log-scope-roles/:id", logScopeRoleHandler.DeleteLogScopeRole) admin.GET("/log-scope-roles/users/:id", logScopeRoleHandler.ListUserLogScopeRoles) admin.POST("/log-scope-roles/users/:id", logScopeRoleHandler.AssignLogScopeRole) admin.DELETE("/log-scope-roles/users/:userId/:assignId", logScopeRoleHandler.RemoveLogScopeRole) admin.POST("/log-scope-roles/preview", logScopeRoleHandler.PreviewLogScope) // 审计策略(保留天数 + 立即清理) // Logan.Li auditSettingsHandler := controller.NewAuditSettingsHandler(db) admin.GET("/audit-settings", auditSettingsHandler.GetAuditSettings) admin.PUT("/audit-settings", auditSettingsHandler.ApplyAuditSettings) } // LDAP 配置路由 ldapHandler := controller.NewLDAPHandler(db) ldapGroup := authorized.Group("/admin/ldap-config") ldapGroup.Use(middleware.AdminAuth()) { ldapGroup.GET("", ldapHandler.GetLDAPConfig) ldapGroup.PUT("", ldapHandler.UpdateLDAPConfig) ldapGroup.POST("/test", ldapHandler.TestLDAPConnection) ldapGroup.POST("/users", ldapHandler.ListLDAPUsers) ldapGroup.POST("/import", ldapHandler.BatchImportLDAP) ldapGroup.POST("/ou-list", ldapHandler.ListLDAPOUs) ldapGroup.POST("/create-ou", ldapHandler.CreateLDAPOU) ldapGroup.POST("/create-user", ldapHandler.CreateLDAPUser) ldapGroup.POST("/delete-user", ldapHandler.DeleteLDAPUser) ldapGroup.POST("/update-user", ldapHandler.UpdateLDAPUser) } // 仪表盘路由 dashboardHandler := controller.NewDashboardHandler(db, redisCache) dashboard := authorized.Group("/dashboard") { dashboard.GET("/stats", dashboardHandler.GetStats) dashboard.GET("/recent-alerts", dashboardHandler.GetRecentAlerts) dashboard.GET("/recent-releases", dashboardHandler.GetRecentReleases) dashboard.GET("/metrics", dashboardHandler.GetMetrics) } // 服务器路由 serverHandlerV2 := controller.NewServerHandlerV2(svcs.Server, db) servers := authorized.Group("/servers") { servers.GET("", serverHandlerV2.ListServers) servers.GET("/stats", serverHandlerV2.GetServerStats) servers.GET("/:id", serverHandlerV2.GetServer) servers.POST("", serverHandlerV2.CreateServer) servers.PUT("/:id", serverHandlerV2.UpdateServer) servers.DELETE("/:id", serverHandlerV2.DeleteServer) servers.POST("/batch-delete", serverHandlerV2.BatchDeleteServers) servers.POST("/batch", serverHandlerV2.BatchCreateServers) // Agent 远程安装 // Logan.Li servers.POST("/:id/install-agent", agentInstallHandler.InstallAgent) servers.POST("/install-agent", agentInstallHandler.BatchInstallAgent) // SFTP 文件浏览 // Logan.Li sftpHandler := controller.NewSFTPHandler(db) servers.GET("/:id/files", sftpHandler.ListFiles) servers.GET("/:id/files/download", sftpHandler.DownloadFile) servers.POST("/:id/files/upload", sftpHandler.UploadFile) servers.DELETE("/:id/files", sftpHandler.DeleteFile) servers.POST("/:id/files/mkdir", sftpHandler.Mkdir) } // 云账单处理器(云账号同步账单路由共用) // Logan.Li billingHandler := controller.NewBillingHandler(db, &cfg.Billing) // 云账号路由 cloudAccountHandler := controller.NewCloudAccountHandler(db) cloudAccounts := authorized.Group("/cloud-accounts") { cloudAccounts.GET("", cloudAccountHandler.ListCloudAccounts) cloudAccounts.POST("", cloudAccountHandler.CreateCloudAccount) cloudAccounts.PUT("/:id", cloudAccountHandler.UpdateCloudAccount) cloudAccounts.DELETE("/:id", cloudAccountHandler.DeleteCloudAccount) // 云同步路由 — 区域同步 / 主机发现 / 导入主机 // Logan.Li syncHandler := controller.NewCloudSyncHandler(db, cfg.JWT.Secret) cloudAccounts.POST("/:id/sync-regions", syncHandler.SyncRegions) cloudAccounts.GET("/:id/regions", syncHandler.GetAccountRegions) cloudAccounts.POST("/:id/discover-instances", syncHandler.DiscoverInstances) cloudAccounts.POST("/:id/import-instances", syncHandler.ImportInstances) cloudAccounts.POST("/:id/sync-billing", billingHandler.SyncAccountBilling) } // 域名路由 domainHandler := controller.NewDomainHandler(db) domains := authorized.Group("/domains") { domains.GET("", domainHandler.ListDomains) domains.POST("", domainHandler.CreateDomain) domains.PUT("/:id", domainHandler.UpdateDomain) domains.POST("/:id/check-ssl", domainHandler.CheckDomainSSL) domains.DELETE("/:id", domainHandler.DeleteDomain) } // 云平台路由 platformHandler := controller.NewPlatformHandler(db) platforms := authorized.Group("/platforms") { platforms.GET("", platformHandler.ListPlatforms) platforms.POST("", platformHandler.CreatePlatform) platforms.PUT("/:id", platformHandler.UpdatePlatform) platforms.DELETE("/:id", platformHandler.DeletePlatform) } // 区域路由 regionHandler := controller.NewRegionHandler(db) regions := authorized.Group("/regions") { regions.GET("", regionHandler.ListRegions) regions.POST("", regionHandler.CreateRegion) regions.PUT("/:id", regionHandler.UpdateRegion) regions.DELETE("/batch-delete", regionHandler.BatchDeleteRegions) // Logan.Li regions.DELETE("/:id", regionHandler.DeleteRegion) } // 云账单路由 billings := authorized.Group("/cloud-billings") { billings.GET("", billingHandler.ListBillings) billings.POST("", billingHandler.CreateBilling) billings.POST("/batch", billingHandler.BatchCreateBillings) billings.DELETE("/:id", billingHandler.DeleteBilling) billings.GET("/stats", billingHandler.GetBillingStats) billings.GET("/cost-analysis", billingHandler.GetBillingCostAnalysis) billings.GET("/settings", billingHandler.GetBillingSettings) billings.PUT("/settings", middleware.AdminAuth(), billingHandler.SaveBillingSettings) billings.GET("/providers", billingHandler.GetProviderOptions) billings.POST("/sync", billingHandler.SyncYesterdayBillings) } billingAlerts := authorized.Group("/billing-alerts") { billingAlerts.GET("", billingHandler.ListAlertRules) billingAlerts.POST("", billingHandler.CreateAlertRule) billingAlerts.PUT("/:id", billingHandler.UpdateAlertRule) billingAlerts.DELETE("/:id", billingHandler.DeleteAlertRule) billingAlerts.POST("/:id/toggle", billingHandler.ToggleAlertRule) } // 资源模型路由 resourceModelHandler := controller.NewResourceModelHandler(db) resourceModels := authorized.Group("/resource-models") { resourceModels.GET("", resourceModelHandler.ListResourceModels) resourceModels.POST("", resourceModelHandler.CreateResourceModel) resourceModels.PUT("/:id", resourceModelHandler.UpdateResourceModel) resourceModels.DELETE("/:id", resourceModelHandler.DeleteResourceModel) } // ============================================================================ // 集群管理路由 (cluster CRUD + sync + topology — 合法 ID 路由) // 资源列举路由 (nodes/pods/deployments/services/...) 保留向后兼容, // 但应优先使用 /kubernetes/:clusterCode/... (Kuboard code 路由)。详见 ROADMAP A1。 // ============================================================================ clusters := authorized.Group("/kubernetes-clusters") { clusters.GET("", k8sHandler.ListClusters) clusters.GET("/:id", k8sHandler.GetCluster) clusters.GET("/:id/detail", k8sHandler.GetClusterDetail) // 编辑用详情(含 has_token 标记) // Logan.Li clusters.POST("", k8sHandler.CreateCluster) clusters.PUT("/:id", k8sHandler.UpdateCluster) clusters.DELETE("/:id", k8sHandler.DeleteCluster) clusters.POST("/:id/sync", k8sHandler.SyncCluster) // 同步集群资源 // Logan.Li clusters.GET("/:id/nodes", k8sHandler.ListNodes) // Deprecated: use GET /kubernetes/:clusterCode/nodes clusters.GET("/:id/nodes/:name", k8sHandler.GetNodeDetail) // M10 节点详情 // Logan.Li clusters.GET("/:id/pods", k8sHandler.ListPods) // Deprecated: use GET /kubernetes/:clusterCode/pods clusters.GET("/:id/deployments", k8sHandler.ListDeployments) // Deprecated: use GET /kubernetes/:clusterCode/deployments clusters.GET("/:id/services", k8sHandler.ListServices) // Deprecated: use GET /kubernetes/:clusterCode/services clusters.GET("/:id/ingresses", k8sHandler.ListIngresses) // Deprecated: use GET /kubernetes/:clusterCode/ingresses clusters.GET("/:id/topology", k8sHandler.GetTopology) // 获取拓扑布局 // Logan.Li clusters.PUT("/:id/topology", k8sHandler.SaveTopology) // 保存拓扑布局 // Logan.Li // Pod 日志 // Logan.Li clusters.GET("/:id/namespaces/:namespace/pods/:podName/logs", k8sHandler.GetPodLogs) // Pod 终端 exec (命令执行 / 文件浏览) // Logan.Li clusters.POST("/:id/namespaces/:namespace/pods/:podName/exec", k8sHandler.ExecInPod) // Deployment 扩缩容 & 重启 // Logan.Li clusters.POST("/:id/namespaces/:namespace/deployments/:name/scale", k8sHandler.ScaleDeployment) clusters.POST("/:id/namespaces/:namespace/deployments/:name/restart", k8sHandler.RestartDeployment) // Deployment 暂停/恢复滚动更新 // Logan.Li M5 clusters.POST("/:id/namespaces/:namespace/deployments/:name/pause", k8sHandler.PauseDeployment) clusters.POST("/:id/namespaces/:namespace/deployments/:name/resume", k8sHandler.ResumeDeployment) // Deployment CI 集成 (Webhook 更新镜像) // Logan.Li clusters.POST("/:id/namespaces/:namespace/deployments/:name/update-image", k8sHandler.UpdateDeploymentImage) // HPA 管理 // Logan.Li clusters.GET("/:id/hpas", k8sHandler.ListHPAs) clusters.POST("/:id/hpas", k8sHandler.CreateHPA) clusters.DELETE("/:id/namespaces/:namespace/hpas/:name", k8sHandler.DeleteHPA) // CronJob 管理 // Logan.Li clusters.GET("/:id/cronjobs", k8sHandler.ListCronJobs) clusters.POST("/:id/cronjobs", k8sHandler.CreateCronJob) clusters.POST("/:id/namespaces/:namespace/cronjobs/:name/suspend", k8sHandler.SuspendCronJob) clusters.POST("/:id/namespaces/:namespace/cronjobs/:name/trigger", k8sHandler.TriggerCronJob) clusters.DELETE("/:id/namespaces/:namespace/cronjobs/:name", k8sHandler.DeleteCronJob) // ReplicaSet 列表 / Deployment 回滚 / 历史版本 // Logan.Li clusters.GET("/:id/namespaces/:namespace/replicasets", k8sHandler.ListReplicaSetsNS) clusters.GET("/:id/namespaces/:namespace/deployments/:name/revisions", k8sHandler.ListDeploymentRevisionsNS) clusters.POST("/:id/namespaces/:namespace/deployments/:name/rollback", k8sHandler.RollbackDeploymentNS) // Pod 文件浏览 / 下载 / 删除 // Logan.Li clusters.POST("/:id/namespaces/:namespace/pods/:podName/files/list", k8sHandler.ListPodFilesNS) clusters.GET("/:id/namespaces/:namespace/pods/:podName/files/download", k8sHandler.DownloadPodFileNS) clusters.POST("/:id/namespaces/:namespace/pods/:podName/files/upload", k8sHandler.UploadPodFileNS) clusters.DELETE("/:id/namespaces/:namespace/pods/:podName", k8sHandler.DeletePodNS) // Namespace // Logan.Li clusters.GET("/:id/namespaces", k8sHandler.ListNamespaces) } // ============================================================================ // Kuboard-style namespace-scoped routes (/kubernetes/{clusterCode}/namespace/{ns}/...) // ============================================================================ kubernetesRouter := authorized.Group("/kubernetes") { // Namespace overview kubernetesRouter.GET("/:clusterCode/namespace/:namespace", func(c *gin.Context) { k8sHandler.ListDeploymentsNS(c) }) // Node detail (cluster-scoped, not namespace-scoped) // M10 kubernetesRouter.GET("/:clusterCode/nodes/:name", k8sHandler.GetNodeDetail) // Cluster-scoped node list (canonical — replaces /kubernetes-clusters/:id/nodes) kubernetesRouter.GET("/:clusterCode/nodes", k8sHandler.ListNodes) // Deployments kubernetesRouter.GET("/:clusterCode/namespace/:namespace/deployments", k8sHandler.ListDeploymentsNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/deployments/:name", k8sHandler.GetDeploymentNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/scale", k8sHandler.ScaleDeploymentNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/restart", k8sHandler.RestartDeploymentNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/pause", k8sHandler.PauseDeploymentNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/resume", k8sHandler.ResumeDeploymentNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/update-image", k8sHandler.UpdateDeploymentImageNS) // Pods kubernetesRouter.GET("/:clusterCode/namespace/:namespace/pods", k8sHandler.ListPodsNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/pods/:podName/logs", k8sHandler.GetPodLogsNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/pods/:podName/exec", k8sHandler.ExecInPodNS) // Services kubernetesRouter.GET("/:clusterCode/namespace/:namespace/services", k8sHandler.ListServicesNS) // Ingresses kubernetesRouter.GET("/:clusterCode/namespace/:namespace/ingresses", k8sHandler.ListIngressesNS) // IngressClass 列表(可视化编辑 Ingress 时选择 ingressClassName 用) // Logan.Li kubernetesRouter.GET("/:clusterCode/ingressclasses", k8sHandler.ListIngressClasses) // HPA kubernetesRouter.GET("/:clusterCode/namespace/:namespace/hpas", k8sHandler.ListHPAsNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/hpas", k8sHandler.CreateHPANS) kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/hpas/:name", k8sHandler.DeleteHPANS) // CronJob kubernetesRouter.GET("/:clusterCode/namespace/:namespace/cronjobs", k8sHandler.ListCronJobsNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/cronjobs", k8sHandler.CreateCronJobNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/cronjobs/:name/suspend", k8sHandler.SuspendCronJobNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/cronjobs/:name/trigger", k8sHandler.TriggerCronJobNS) kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/cronjobs/:name", k8sHandler.DeleteCronJobNS) // 🆕 ReplicaSet 列表 // Logan.Li kubernetesRouter.GET("/:clusterCode/namespace/:namespace/replicasets", k8sHandler.ListReplicaSetsNS) // 🆕 Deployment 回滚 / 发布历史 // Logan.Li kubernetesRouter.GET("/:clusterCode/namespace/:namespace/deployments/:name/revisions", k8sHandler.ListDeploymentRevisionsNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/rollback", k8sHandler.RollbackDeploymentNS) // 🆕 Pod 文件浏览 / 下载 / 删除 // Logan.Li kubernetesRouter.POST("/:clusterCode/namespace/:namespace/pods/:podName/files/list", k8sHandler.ListPodFilesNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/pods/:podName/files/download", k8sHandler.DownloadPodFileNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/pods/:podName/files/upload", k8sHandler.UploadPodFileNS) kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/pods/:podName", k8sHandler.DeletePodNS) // ConfigMap / Secret kubernetesRouter.GET("/:clusterCode/namespace/:namespace/configmaps", k8sHandler.ListConfigMaps) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/secrets", k8sHandler.ListSecrets) // Namespace list kubernetesRouter.GET("/:clusterCode/namespaces", k8sHandler.ListNamespaces) // 🆕 M14: Namespace 管理看板 (detail + CRUD) kubernetesRouter.GET("/:clusterCode/namespaces/detail", k8sHandler.GetNamespacesDetail) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/detail", k8sHandler.GetNamespaceDetailHandler) kubernetesRouter.POST("/:clusterCode/namespaces", k8sHandler.CreateNamespaceHandler) kubernetesRouter.DELETE("/:clusterCode/namespaces/:namespace", k8sHandler.DeleteNamespaceHandler) // All-namespace listing (no ns filter) — canonical code-based routes (A1) kubernetesRouter.GET("/:clusterCode/deployments", k8sHandler.ListDeploymentsAllNS) kubernetesRouter.GET("/:clusterCode/pods", k8sHandler.ListPodsAllNS) kubernetesRouter.GET("/:clusterCode/hpas", k8sHandler.ListHPAsAllNS) kubernetesRouter.GET("/:clusterCode/services", k8sHandler.ListServicesAllNS) kubernetesRouter.GET("/:clusterCode/ingresses", k8sHandler.ListIngressesAllNS) kubernetesRouter.GET("/:clusterCode/cronjobs", k8sHandler.ListCronJobsAllNS) // 🆕 Pod Metrics (kubectl top pods) kubernetesRouter.GET("/:clusterCode/metrics/pods", k8sHandler.GetPodMetrics) // 🆕 Events kubernetesRouter.GET("/:clusterCode/events", k8sHandler.ListEvents) kubernetesRouter.GET("/:clusterCode/events/summary", k8sHandler.GetEventsSummary) // 🆕 Capacity Analysis kubernetesRouter.GET("/:clusterCode/capacity", k8sHandler.GetCapacityAnalysis) // 🆕 YAML Apply kubernetesRouter.POST("/:clusterCode/yaml/apply", k8sHandler.ApplyYAML) // 🆕 批量导出资源 (Deployment+Service+Ingress+ConfigMap+Secret) // Logan.Li kubernetesRouter.GET("/:clusterCode/export", k8sHandler.ExportResourcesAllNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/export", k8sHandler.ExportResourcesNS) // PVC (存储) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/pvcs", k8sHandler.ListPVCsNS) kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/pvcs/:name", k8sHandler.DeletePVCNS) // RBAC — ServiceAccount / Role / RoleBinding kubernetesRouter.GET("/:clusterCode/namespace/:namespace/serviceaccounts", k8sHandler.ListServiceAccountsNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/roles", k8sHandler.ListRolesNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/rolebindings", k8sHandler.ListRoleBindingsNS) // StatefulSet / DaemonSet kubernetesRouter.GET("/:clusterCode/namespace/:namespace/statefulsets", k8sHandler.ListStatefulSetsNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/daemonsets", k8sHandler.ListDaemonSetsNS) // StatefulSet operations (Kuboard code routes) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/statefulsets/:name", k8sHandler.GetStatefulSetDetailNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/statefulsets/:name/scale", k8sHandler.ScaleStatefulSetNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/statefulsets/:name/restart", k8sHandler.RestartStatefulSetNS) // DaemonSet operations (Kuboard code routes) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/daemonsets/:name", k8sHandler.GetDaemonSetDetailNS) kubernetesRouter.POST("/:clusterCode/namespace/:namespace/daemonsets/:name/restart", k8sHandler.RestartDaemonSetNS) // StatefulSet/DaemonSet YAML (specific routes to avoid Gin radix tree conflict with generic /:resource/:name/yaml) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/statefulsets/:name/yaml", k8sHandler.GetResourceYAMLNS) kubernetesRouter.PUT("/:clusterCode/namespace/:namespace/statefulsets/:name/yaml", k8sHandler.UpdateResourceYAMLNS) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/daemonsets/:name/yaml", k8sHandler.GetResourceYAMLNS) kubernetesRouter.PUT("/:clusterCode/namespace/:namespace/daemonsets/:name/yaml", k8sHandler.UpdateResourceYAMLNS) // YAML view/edit (generic — works for resources without specific static routes) kubernetesRouter.GET("/:clusterCode/namespace/:namespace/:resource/:name/yaml", k8sHandler.GetResourceYAMLNS) kubernetesRouter.PUT("/:clusterCode/namespace/:namespace/:resource/:name/yaml", k8sHandler.UpdateResourceYAMLNS) kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/:resource/:name/yaml", k8sHandler.DeleteResourceYAMLNS) // 🆕 M13: 多集群资源对比看板 kubernetesRouter.GET("/compare", k8sHandler.GetMultiClusterComparison) } // 日志数据源 handler 需要提前初始化,以便注入告警引擎执行日志告警规则。// Logan.Li logDSHandler := controller.NewLogDSHandler(db) // 告警引擎(分布式锁 — 多副本部署时仅 Leader 执行检查) alertEngine := controller.NewAlertEngine(db, redisCache, logDSHandler) // 告警路由 alertHandler := controller.NewAlertHandler(db) alerts := authorized.Group("/alerts") { alerts.GET("", alertHandler.ListAlerts) alerts.GET("/rules", alertHandler.ListRules) alerts.POST("/rules", alertHandler.CreateRule) alerts.PUT("/rules/:id", alertHandler.UpdateRule) alerts.DELETE("/rules/batch-delete", alertHandler.BatchDeleteRules) alerts.DELETE("/rules/:id", alertHandler.DeleteRule) alerts.POST("/rules/:id/toggle", alertHandler.ToggleRule) alerts.POST("/:id/ack", alertHandler.AcknowledgeAlert) alerts.GET("/notify-channels", alertHandler.ListNotifyChannels) alerts.POST("/notify-channels", alertHandler.CreateNotifyChannel) alerts.PUT("/notify-channels/:id", alertHandler.UpdateNotifyChannel) alerts.DELETE("/notify-channels/:id", alertHandler.DeleteNotifyChannel) alerts.POST("/notify-channels/:id/test", alertHandler.TestNotifyChannel) alerts.POST("/quick-setup", alertHandler.QuickSetupRules) // 报警联系人 alertContactV2 := controller.NewAlertContactHandlerV2(svcs.AlertContact) alerts.GET("/contacts", alertContactV2.ListContacts) alerts.POST("/contacts", alertContactV2.CreateContact) alerts.PUT("/contacts/:id", alertContactV2.UpdateContact) alerts.DELETE("/contacts/:id", alertContactV2.DeleteContact) // 报警联系组 alertGroupV2 := controller.NewAlertContactGroupHandlerV2(svcs.AlertContactGroup) alerts.GET("/contact-groups", alertGroupV2.ListGroups) alerts.POST("/contact-groups", alertGroupV2.CreateGroup) alerts.PUT("/contact-groups/:id", alertGroupV2.UpdateGroup) alerts.DELETE("/contact-groups/:id", alertGroupV2.DeleteGroup) // 告警集合通知策略 // Logan.Li alerts.GET("/notify-policies", alertHandler.ListNotifyPolicies) alerts.PUT("/notify-policies/:category", alertHandler.UpsertNotifyPolicy) alerts.POST("/notify-policies/:category/test", alertHandler.TestNotifyPolicy) alerts.GET("/notify-message-settings", alertHandler.GetNotifyMessageSettings) alerts.PUT("/notify-message-settings", alertHandler.SaveNotifyMessageSettings) // 告警静默规则 alerts.GET("/silences", alertHandler.ListSilences) alerts.POST("/silences", alertHandler.CreateSilence) alerts.PUT("/silences/:id", alertHandler.UpdateSilence) alerts.DELETE("/silences/:id", alertHandler.DeleteSilence) alerts.POST("/silences/:id/toggle", alertHandler.ToggleSilence) // 监控指标目录 + 统一告警 + 中间件/站点规则 // Logan.Li alerts.GET("/metric-catalog", alertHandler.GetMetricCatalog) alerts.GET("/unified", alertHandler.ListUnifiedAlerts) alerts.GET("/unified-rules", alertHandler.ListUnifiedAlertRules) alerts.GET("/monitor-rules", alertHandler.ListMonitorAlertRules) alerts.POST("/monitor-rules", alertHandler.CreateMonitorAlertRule) alerts.PUT("/monitor-rules/:id", alertHandler.UpdateMonitorAlertRule) alerts.DELETE("/monitor-rules/:id", alertHandler.DeleteMonitorAlertRule) alerts.POST("/monitor-quick-setup", alertHandler.QuickSetupMonitorRules) alerts.POST("/unified/:source/:id/resolve", alertHandler.ResolveUnifiedAlert) // 告警引擎状态 — 查看当前 Leader 副本和分布式锁状态 alerts.GET("/engine/status", func(c *gin.Context) { c.JSON(200, model.Response{Code: 200, Data: alertEngine.GetEngineStatus()}) }) } // 流水线路由 pipelines := authorized.Group("/pipelines") { pipelines.GET("", pipelineHandler.ListPipelines) pipelines.POST("", pipelineHandler.CreatePipeline) // 需要流水线权限的路由 pipelineScoped := pipelines.Group("/:code") pipelineScoped.Use(middleware.PipelineAccess(db)) { pipelineScoped.GET("", pipelineHandler.GetPipeline) pipelineScoped.PUT("", pipelineHandler.UpdatePipeline) pipelineScoped.DELETE("", pipelineHandler.DeletePipeline) pipelineScoped.POST("/trigger", pipelineHandler.TriggerPipeline) pipelineScoped.GET("/runs", pipelineHandler.ListRuns) pipelineScoped.POST("/runs/:runId/stop", pipelineHandler.StopPipelineRun) pipelineScoped.POST("/runs/batch-delete", pipelineHandler.BatchDeleteRuns) pipelineScoped.GET("/runs/:runId/log", pipelineHandler.GetRunLog) // 队列管理 pipelineScoped.GET("/queue", pipelineHandler.GetPipelineQueue) pipelineScoped.DELETE("/queue/:runId", pipelineHandler.CancelQueueItem) // 成员管理 pipelineScoped.GET("/members", pipelineHandler.ListPipelineMembers) pipelineScoped.POST("/members", pipelineHandler.AddPipelineMember) pipelineScoped.DELETE("/members/:memberId", pipelineHandler.RemovePipelineMember) // 组授权 pipelineScoped.POST("/groups", pipelineHandler.AssignGroupToPipeline) } } // 用户组管理路由 groups := authorized.Group("/deploy/groups") { groups.GET("", pipelineHandler.ListGroups) groups.POST("", pipelineHandler.CreateGroup) groups.PUT("/:id", pipelineHandler.UpdateGroup) groups.DELETE("/:id", pipelineHandler.DeleteGroup) groups.GET("/:id/members", pipelineHandler.ListGroupMembers) groups.POST("/:id/members", pipelineHandler.AddGroupMember) groups.DELETE("/:id/members/:memberId", pipelineHandler.RemoveGroupMember) } // 环境管理路由 environments := authorized.Group("/deploy/environments") { environments.GET("", pipelineHandler.ListEnvironments) environments.POST("", pipelineHandler.CreateEnvironment) environments.PUT("/:id", pipelineHandler.UpdateEnvironment) environments.DELETE("/:id", pipelineHandler.DeleteEnvironment) } // 构建节点路由(Jenkins Agent 风格 SSH 节点) // Logan.Li buildNodes := authorized.Group("/deploy/build-nodes") { buildNodes.GET("", pipelineHandler.ListBuildNodes) buildNodes.PUT("/master", pipelineHandler.UpdateBuildMaster) buildNodes.POST("", pipelineHandler.CreateBuildNode) buildNodes.PUT("/:id", pipelineHandler.UpdateBuildNode) buildNodes.DELETE("/:id", pipelineHandler.DeleteBuildNode) buildNodes.POST("/:id/test", pipelineHandler.TestBuildNode) } // Jenkins 外部 CI 接入:同步 Jobs 并通过 Jenkins API 触发构建。 // Logan.Li jenkins := authorized.Group("/deploy/jenkins") { jenkins.GET("/config", pipelineHandler.GetJenkinsConfig) jenkins.PUT("/config", pipelineHandler.SaveJenkinsConfig) jenkins.POST("/test", pipelineHandler.TestJenkinsConfig) jenkins.POST("/sync", pipelineHandler.SyncJenkinsJobs) jenkins.GET("/refs", pipelineHandler.GetJenkinsRefs) } // 应用发布路由 releases := authorized.Group("/releases") { releases.GET("", pipelineHandler.ListReleases) releases.POST("", pipelineHandler.CreateRelease) releases.POST("/:id/approve", pipelineHandler.ApproveRelease) releases.POST("/:id/reject", pipelineHandler.RejectRelease) // 驳回发布 // Logan.Li releases.POST("/:id/deploy", pipelineHandler.DeployRelease) releases.POST("/:id/rollback", pipelineHandler.RollbackRelease) } // 工具配置路由(发布配置 Tab ④)// Logan.Li toolConfigHandler := controller.NewToolConfigHandler(db, ti) tools := authorized.Group("/deploy/tools") { tools.GET("", toolConfigHandler.ListTools) tools.GET("/:id", toolConfigHandler.GetTool) tools.PUT("/:id", toolConfigHandler.UpdateTool) tools.POST("/:id/install", toolConfigHandler.InstallTool) tools.POST("/:id/uninstall", toolConfigHandler.UninstallTool) tools.POST("/:id/check", toolConfigHandler.CheckToolStatus) tools.GET("/:id/versions", toolConfigHandler.GetToolVersions) } // 自动化运维路由 automationHandler := controller.NewAutomationHandler(db) autoWrite := middleware.AutomationWrite(db) cronJobs := authorized.Group("/cron-jobs") { cronJobs.GET("", automationHandler.ListCronJobs) cronJobs.POST("", autoWrite, automationHandler.CreateCronJob) cronJobs.GET("/:id", automationHandler.GetCronJob) cronJobs.PUT("/:id", autoWrite, automationHandler.UpdateCronJob) cronJobs.DELETE("/batch-delete", autoWrite, automationHandler.BatchDeleteCronJobs) cronJobs.DELETE("/:id", autoWrite, automationHandler.DeleteCronJob) cronJobs.POST("/:id/toggle", autoWrite, automationHandler.ToggleCronJob) cronJobs.POST("/:id/execute", autoWrite, automationHandler.ExecuteCronJob) } // 内置系统任务(告警引擎 / 数据清理等) // Logan.Li sysTaskHandler := controller.NewSystemTaskHandler(db, cfg.Database.Driver, alertEngine) sysTasks := authorized.Group("/system-tasks") { sysTasks.GET("", sysTaskHandler.ListSystemTasks) sysTasks.POST("/:code/run", autoWrite, sysTaskHandler.RunSystemTask) } scripts := authorized.Group("/scripts") { scripts.GET("/runtime", automationHandler.GetScriptRuntime) scripts.GET("", automationHandler.ListScripts) scripts.POST("", autoWrite, automationHandler.CreateScript) scripts.GET("/:id", automationHandler.GetScript) scripts.POST("/batch-delete", autoWrite, automationHandler.BatchDeleteScripts) scripts.DELETE("/:id", autoWrite, automationHandler.DeleteScript) scripts.PUT("/:id", autoWrite, automationHandler.UpdateScript) scripts.POST("/:id/execute", autoWrite, automationHandler.ExecuteScript) } // 远程执行路由 — Go 原生 SSH 批量执行替代 Ansible // Logan.Li remoteExecHandler := controller.NewRemoteExecHandler(db) remoteExec := authorized.Group("/remote-exec") { remoteExec.POST("/execute", remoteExecHandler.BatchExec) remoteExec.POST("/upload", remoteExecHandler.BatchUpload) remoteExec.POST("/upload-file", remoteExecHandler.UploadFile) remoteExec.GET("/hosts", remoteExecHandler.MatchHosts) remoteExec.POST("/server/:id/exec", remoteExecHandler.ExecOnServer) } // 任务执行记录(脚本/定时任务执行历史,不含 Ansible) authorized.GET("/task-executions", automationHandler.ListExecutions) // 日志监控路由 // Logan.Li logHandler := controller.NewLogHandler(db) logProxyHandler := controller.NewLogProxyHandler(logDSHandler, db) logs := authorized.Group("/logs") { logs.GET("", logHandler.QueryLogs) logs.GET("/sources", logHandler.ListSources) logs.POST("/sources", logHandler.CreateSource) logs.DELETE("/sources/:id", logHandler.DeleteSource) logs.POST("/loki/query", logProxyHandler.QueryLoki) logs.POST("/elasticsearch/query", logProxyHandler.QueryES) logs.GET("/loki/labels", logProxyHandler.ListLokiLabels) logs.GET("/loki/labels/:name/values", logProxyHandler.ListLokiLabelValues) logs.POST("/loki/histogram", logProxyHandler.LokiHistogram) logs.POST("/elasticsearch/histogram", logProxyHandler.ESHistogram) logs.GET("/elasticsearch/mapping", logProxyHandler.ESMapping) } logDSGroup := authorized.Group("/log-datasources") { logDSGroup.GET("", logDSHandler.List) logDSGroup.GET("/indices", logDSHandler.ListIndices) logDSGroup.GET("/:id/indices", logDSHandler.ListIndicesByID) logDSGroup.GET("/:id", logDSHandler.Get) logDSGroup.POST("", logDSHandler.Create) logDSGroup.PUT("/:id", logDSHandler.Update) logDSGroup.DELETE("/:id", logDSHandler.Delete) logDSGroup.POST("/:id/default", logDSHandler.SetDefault) logDSGroup.POST("/test", logDSHandler.TestConnection) } // 审批流程路由 approvalHandler := controller.NewApprovalHandler(db) approvals := authorized.Group("/approvals") { approvals.GET("/templates", approvalHandler.ListTemplates) approvals.POST("/templates", approvalHandler.CreateTemplate) approvals.GET("/templates/:id", approvalHandler.GetTemplate) approvals.PUT("/templates/:id", approvalHandler.UpdateTemplate) approvals.DELETE("/templates/:id", approvalHandler.DeleteTemplate) approvals.GET("/processes", approvalHandler.ListProcesses) approvals.POST("/processes", approvalHandler.CreateProcess) approvals.GET("/processes/:id", approvalHandler.GetProcess) approvals.POST("/processes/:id/approve", approvalHandler.ApproveProcess) approvals.POST("/processes/:id/reject", approvalHandler.RejectProcess) } // 审批流程配置(工作流定义) workflowHandler := controller.NewWorkflowHandler(db) workflows := authorized.Group("/approval-workflows") { workflows.GET("", workflowHandler.ListWorkflows) workflows.POST("", workflowHandler.CreateWorkflow) workflows.GET("/:id", workflowHandler.GetWorkflow) workflows.PUT("/:id", workflowHandler.UpdateWorkflow) workflows.DELETE("/:id", workflowHandler.DeleteWorkflow) workflows.PUT("/:id/default", workflowHandler.SetDefaultWorkflow) workflows.GET("/:id/steps", workflowHandler.GetWorkflowSteps) } // 导航路由 navHandler := controller.NewNavigationHandler(db) navigations := authorized.Group("/navigations") { navigations.GET("/groups", navHandler.ListGroups) navigations.POST("/groups", navHandler.CreateGroup) navigations.PUT("/groups/:id", navHandler.UpdateGroup) navigations.DELETE("/groups/:id", navHandler.DeleteGroup) navigations.GET("/links", navHandler.ListLinks) navigations.POST("/links", navHandler.CreateLink) navigations.PUT("/links/:id", navHandler.UpdateLink) navigations.DELETE("/links/:id", navHandler.DeleteLink) navigations.POST("/links/:id/favorite", navHandler.ToggleFavorite) } // 审计日志路由 auditHandler := controller.NewAuditHandler(db) audit := authorized.Group("/audit") { audit.GET("/logs", auditHandler.ListAuditLogs) audit.GET("/logs/:id", auditHandler.GetAuditLogDetail) audit.GET("/modules", auditHandler.GetAuditModules) audit.GET("/actions", auditHandler.GetAuditActions) audit.GET("/logs/export", auditHandler.ExportAuditLogs) audit.GET("/statistics", auditHandler.GetAuditStatistics) audit.POST("/logs/clear", auditHandler.ClearAuditLogs) } // 终端会话审计路由(WebSSH 录制回放) // Logan.Li terminalSessionHandler := controller.NewTerminalSessionHandler(db, webShellHandler.KillSession) ts := authorized.Group("/terminal-sessions") { ts.GET("", terminalSessionHandler.ListTerminalSessions) ts.POST("/batch-delete", terminalSessionHandler.BatchDeleteTerminalSessions) ts.GET("/:id", terminalSessionHandler.GetTerminalSession) ts.GET("/:id/record", terminalSessionHandler.GetTerminalRecord) ts.DELETE("/:id", terminalSessionHandler.DeleteTerminalSession) ts.POST("/:id/kill", terminalSessionHandler.KillSession) ts.GET("/:id/download", terminalSessionHandler.DownloadSession) ts.POST("/:id/replay-view", terminalSessionHandler.LogReplayView) ts.GET("/:id/stream", terminalSessionHandler.StreamSession) } // Windows RDP 图形会话审计路由(只做录屏帧回放,不做命令审计) // Logan.Li rdpSessionHandler := controller.NewRDPSessionHandler(db, rdpHandler.KillSession) rs := authorized.Group("/rdp-sessions") { rs.GET("", rdpSessionHandler.ListRDPSessions) rs.GET("/:id", rdpSessionHandler.GetRDPSession) rs.GET("/:id/record", rdpSessionHandler.GetRDPRecord) rs.POST("/:id/kill", rdpSessionHandler.KillRDPSession) rs.GET("/:id/download", rdpSessionHandler.DownloadRDPRecord) rs.POST("/:id/replay-view", rdpSessionHandler.LogRDPReplayView) } // 会话命令审计路由(JumpServer 式命令审计) // Logan.Li scHandler := controller.NewSessionCommandHandler(db) sc := authorized.Group("/session-commands") { sc.GET("", scHandler.ListSessionCommands) } // 登录日志路由 // Logan.Li llHandler := controller.NewLoginLogHandler(db) ll := authorized.Group("/login-logs") { ll.GET("", llHandler.ListLoginLogs) } // Agent 采集通道保持既有协议,待按主机绑定的可轮换凭证上线后再强制校验。 // Logan.Li agentHandler := controller.NewAgentHandler(db, redisCache, metricsHub) taskHandler := controller.NewAgentTaskHandler(db) agentGroup := api.Group("/agent", middleware.AgentAuth(db, cfg.Agent.EnforceAuth)) { agentGroup.POST("/report", agentHandler.ReceiveReport) agentGroup.GET("/tasks/poll", taskHandler.PollTasks) agentGroup.POST("/tasks/:task_id/result", taskHandler.SubmitResult) // 健康探针:Agent 拉取本机配置。 agentGroup.GET("/health-probes/config", agentHandler.GetHealthProbesForAgent) // 端口策略:Agent 拉取本机端口过滤策略。 agentGroup.GET("/port-policy", agentHandler.GetPortPolicyForAgent) } // Agent 数据查询 + 任务管理(需要 JWT) agentQuery := authorized.Group("/agent") { agentQuery.POST("/exec", agentInstallHandler.RemoteExec) agentQuery.GET("/latest", agentHandler.GetLatestReports) agentQuery.GET("/history/:hostname", agentHandler.GetHostHistory) agentQuery.GET("/aggregate", agentHandler.GetAggregate) // 指标聚合是控制台维护操作,必须使用用户 JWT,不能由采集 Agent 调用。 // Logan.Li agentQuery.POST("/aggregate", agentHandler.AggregateMetrics) // 远程任务 agentQuery.POST("/tasks", taskHandler.CreateTask) agentQuery.GET("/tasks", taskHandler.ListTasks) agentQuery.GET("/tasks/:id", taskHandler.GetTask) // 告警规则 agentQuery.GET("/rules", taskHandler.ListRules) agentQuery.POST("/rules/quick-setup", taskHandler.QuickSetupRules) agentQuery.POST("/rules", taskHandler.CreateRule) agentQuery.PUT("/rules/:id", taskHandler.UpdateRule) agentQuery.DELETE("/rules/:id", taskHandler.DeleteRule) // 告警事件 agentQuery.GET("/alerts", taskHandler.ListAlerts) agentQuery.POST("/alerts/:id/resolve", taskHandler.ResolveAlert) // Agent 安装/卸载 agentQuery.POST("/uninstall", agentInstallHandler.UninstallAgent) agentQuery.POST("/batch-uninstall", agentInstallHandler.BatchUninstallAgent) agentQuery.POST("/batch-upgrade", agentInstallHandler.BatchUpgradeAgent) // 健康探针管理(CRUD) agentQuery.GET("/health-probes", agentHandler.ListHealthProbes) agentQuery.POST("/health-probes", agentHandler.CreateHealthProbe) agentQuery.PUT("/health-probes/:id", agentHandler.UpdateHealthProbe) agentQuery.DELETE("/health-probes/:id", agentHandler.DeleteHealthProbe) // 端口策略(CRUD) agentQuery.GET("/port-policies/:hostname", agentHandler.GetPortPolicy) agentQuery.PUT("/port-policies/:hostname", agentHandler.SavePortPolicy) } // AI 智能助手 - LLM 配置 + 对话代理(OpenAI 兼容) // Logan.Li llmHandler := controller.NewLLMHandler(db) aiopsContextHandler := controller.NewAIOpsContextHandler(db) aiopsAlertAnalysisHandler := controller.NewAIOpsAlertAnalysisHandler(db) aiopsGroup := authorized.Group("/aiops") { aiopsGroup.GET("/llm-config", llmHandler.GetLLMConfig) aiopsGroup.PUT("/llm-config", llmHandler.SaveLLMConfig) aiopsGroup.POST("/llm-config/test", llmHandler.TestLLMConnection) aiopsGroup.POST("/chat", llmHandler.Chat) aiopsGroup.POST("/chat/stream", llmHandler.ChatStream) aiopsGroup.GET("/chat-history", llmHandler.GetChatHistory) aiopsGroup.DELETE("/chat-history", llmHandler.ClearChatHistory) aiopsGroup.GET("/context/summary", aiopsContextHandler.Summary) aiopsGroup.POST("/context/pack", aiopsContextHandler.BuildPack) aiopsGroup.POST("/alert-analysis", aiopsAlertAnalysisHandler.Analyze) aiopsGroup.GET("/analysis-traces", aiopsAlertAnalysisHandler.ListAnalysisTraces) aiopsGroup.GET("/analysis-traces/:trace_id", aiopsAlertAnalysisHandler.GetAnalysisTrace) } // 指标浏览器 — 监控指标元数据 + 时序查询 // Logan.Li // Agent CLI — AI 运维 Agent(WebSocket 推流 + 会话历史回放) // Logan.Li agentCLIHandler := controller.NewAgentCLIHandler(db) r.GET("/ws/agent-cli", middleware.JWTAuth(&cfg.JWT, db), middleware.PermissionAuth(db, "aiops:agent-cli"), agentCLIHandler.Run) agentCLIGroup := authorized.Group("/aiops/agent-cli", middleware.PermissionAuth(db, "aiops:agent-cli")) { agentCLIGroup.GET("/sessions", agentCLIHandler.ListSessions) agentCLIGroup.GET("/sessions/:id", agentCLIHandler.GetSession) agentCLIGroup.DELETE("/sessions/:id", agentCLIHandler.DeleteSession) } metricsHandler := controller.NewMetricsHandler(db) metricsGroup := authorized.Group("/metrics") { metricsGroup.GET("/targets", metricsHandler.ListTargets) metricsGroup.GET("/list", metricsHandler.ListMetrics) metricsGroup.GET("/query", metricsHandler.QueryValues) metricsGroup.GET("/names", metricsHandler.ListMetricNames) metricsGroup.GET("/top", metricsHandler.TopHosts) } // 中间件监控 — Redis/MySQL 后端直连采集 // Logan.Li mwHandler := controller.NewMiddlewareMonitorHandler(db) mwGroup := authorized.Group("/middleware-monitors") { mwGroup.GET("", mwHandler.ListMiddlewareTargets) mwGroup.POST("/seed-defaults", mwHandler.SeedDefaultMiddlewareTargetsAPI) mwGroup.POST("", mwHandler.CreateMiddlewareTarget) mwGroup.GET("/:id", mwHandler.GetMiddlewareTarget) mwGroup.PUT("/:id", mwHandler.UpdateMiddlewareTarget) mwGroup.DELETE("/:id", mwHandler.DeleteMiddlewareTarget) mwGroup.POST("/:id/test", mwHandler.TestMiddlewareConnection) mwGroup.POST("/collect", mwHandler.CollectNow) mwGroup.GET("/:id/metrics", mwHandler.GetMiddlewareMetrics) } mwHandler.StartCollector(30) // 每 30s 采集一次 // SNMP 设备管理 — 网络设备/服务器硬件 // Logan.Li snmpHandler := controller.NewSNMPHandler(db) snmpGroup := authorized.Group("/snmp") { snmpGroup.GET("/devices", snmpHandler.ListDevices) snmpGroup.POST("/devices", snmpHandler.CreateDevice) snmpGroup.PUT("/devices/:id", snmpHandler.UpdateDevice) snmpGroup.DELETE("/devices/:id", snmpHandler.DeleteDevice) snmpGroup.DELETE("/devices/batch-delete", snmpHandler.BatchDeleteDevices) snmpGroup.GET("/templates", snmpHandler.ListTemplates) snmpGroup.POST("/templates", snmpHandler.CreateTemplate) snmpGroup.GET("/stats", snmpHandler.GetSNMPStats) snmpGroup.POST("/devices/:id/collect", snmpHandler.CollectDeviceNow) snmpGroup.GET("/devices/:id/metrics", snmpHandler.ListDeviceMetrics) snmpGroup.GET("/devices/:id/metrics/series", snmpHandler.ListMetricSeries) snmpGroup.GET("/devices/:id/metrics/history", snmpHandler.QueryMetricHistory) snmpGroup.GET("/overview/metrics", snmpHandler.GetOverviewMetrics) } snmpHandler.StartCollector(300) // 每 5 分钟采集 SNMP 设备,指标保留 7 天 // Logan.Li // Zabbix 代理 — 镜像 Zabbix API 为前端面板可用格式 // Logan.Li zabbixHandler := controller.NewZabbixProxyHandler() zabbixGroup := authorized.Group("/zabbix") { zabbixGroup.POST("/connect", zabbixHandler.Connect) zabbixGroup.GET("/host/:hostid", zabbixHandler.GetHostDetail) } // Prometheus 代理 — 转发 PromQL 查询到 Prometheus 服务器 // Logan.Li promHandler := controller.NewPrometheusProxyHandler() promGroup := authorized.Group("/prometheus") { promGroup.POST("/connect", promHandler.Connect) promGroup.POST("/query", promHandler.Query) promGroup.POST("/query_range", promHandler.QueryRange) promGroup.POST("/dashboard", promHandler.Dashboard) } // Prometheus 数据源管理 — CRUD + 连接测试 // Logan.Li promDSHandler := controller.NewPromDSHandler(db) promDSGroup := authorized.Group("/prometheus-datasources") { promDSGroup.GET("", promDSHandler.List) promDSGroup.GET("/:id", promDSHandler.Get) promDSGroup.POST("", promDSHandler.Create) promDSGroup.PUT("/:id", promDSHandler.Update) promDSGroup.DELETE("/:id", promDSHandler.Delete) promDSGroup.POST("/:id/default", promDSHandler.SetDefault) promDSGroup.POST("/test", promDSHandler.TestConnection) } // Zabbix 数据源管理 — CRUD + 连接测试 // Logan.Li zabbixDSHandler := controller.NewZabbixDSHandler(db) zabbixDSGroup := authorized.Group("/zabbix-datasources") { zabbixDSGroup.GET("", zabbixDSHandler.List) zabbixDSGroup.GET("/:id", zabbixDSHandler.Get) zabbixDSGroup.POST("", zabbixDSHandler.Create) zabbixDSGroup.PUT("/:id", zabbixDSHandler.Update) zabbixDSGroup.DELETE("/:id", zabbixDSHandler.Delete) zabbixDSGroup.POST("/:id/default", zabbixDSHandler.SetDefault) zabbixDSGroup.POST("/test", zabbixDSHandler.TestConnection) } // 链路追踪数据源管理 — CRUD + 测试连接 + 设默认 // Logan.Li traceDSHandler := controller.NewTraceDSHandler(db) traceProxyHandler := controller.NewTraceProxyHandler(traceDSHandler) traceDSGroup := authorized.Group("/trace-datasources") { traceDSGroup.GET("", traceDSHandler.List) traceDSGroup.GET("/:id", traceDSHandler.Get) traceDSGroup.POST("", traceDSHandler.Create) traceDSGroup.PUT("/:id", traceDSHandler.Update) traceDSGroup.DELETE("/:id", traceDSHandler.Delete) traceDSGroup.POST("/:id/default", traceDSHandler.SetDefault) traceDSGroup.POST("/test", traceDSHandler.TestConnection) } // 链路追踪查询代理 — 转发 Jaeger/Tempo API authorized.GET("/traces", traceProxyHandler.GetTraces) authorized.GET("/traces/services", traceProxyHandler.GetServices) authorized.GET("/traces/:traceId", traceProxyHandler.GetTraceDetail) // 凭据管理 — SSH密钥/API Token/密码统一加密管理 // Logan.Li credentialHandlerV2 := controller.NewCredentialHandlerV2(svcs.Credential) credentialHandler := controller.NewCredentialHandler(db, cfg.JWT.Secret) // 仅用于 GetTags/PatchCredential/AssignCredential(待拆分) credGroup := authorized.Group("/credentials") { credGroup.GET("", credentialHandlerV2.ListCredentials) credGroup.GET("/tags", credentialHandler.GetTags) credGroup.POST("", credentialHandlerV2.CreateCredential) credGroup.GET("/:id", credentialHandlerV2.GetCredential) credGroup.PUT("/:id", credentialHandlerV2.UpdateCredential) credGroup.PATCH("/:id", credentialHandler.PatchCredential) credGroup.DELETE("/:id", credentialHandlerV2.DeleteCredential) } // 服务器凭据关联 // Logan.Li authorized.POST("/servers/:id/assign-credential", credentialHandler.AssignCredential) // 站点拨测 — HTTP/TCP/DNS/PING 主动监控 // Logan.Li siteProbeWorker := siteprobe.NewWorker(db) siteHandler := controller.NewSiteHandler(db, siteProbeWorker) siteGroup := authorized.Group("/site") { siteGroup.GET("/tasks", siteHandler.ListTasks) siteGroup.POST("/tasks", siteHandler.CreateTask) siteGroup.PUT("/tasks/:id", siteHandler.UpdateTask) siteGroup.DELETE("/tasks/:id", siteHandler.DeleteTask) siteGroup.DELETE("/tasks/batch-delete", siteHandler.BatchDeleteTasks) siteGroup.POST("/tasks/:id/probe", siteHandler.ProbeNow) siteGroup.GET("/results", siteHandler.ListResults) siteGroup.GET("/stats", siteHandler.GetSiteStats) } siteProbeWorker.Start(10) // 启动告警引擎(每 30 秒检查一次;alertEngine 在告警路由上方创建) // Logan.Li go func() { ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for range ticker.C { start := time.Now() alertEngine.Check() systask.Record("alert_engine", "success", "", time.Since(start)) } }() }