Files
aiops/backend/cmd/main.go
T
attacker 7d6674bddd init: EZOps AIOps 智能运维平台
- 前端: React 18 + TypeScript + Vite + Tailwind CSS + shadcn/ui
- 后端: Go + Gin + GORM + JWT (golang-jwt/jwt/v5)
- 功能: 服务器管理、K8s集群、监控告警、CI/CD、自动化运维、审批流程、审计日志
- 文档: 设计文档(ROADMAP/PDD/架构/模块)
2026-06-13 23:09:47 +08:00

140 lines
3.0 KiB
Go

package main
import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"ezops/internal/api/routes"
"ezops/internal/config"
"ezops/pkg/database"
"ezops/pkg/logger"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// 版本信息(通过编译时 ldflags 注入)
var (
Version = "dev"
BuildTime = "unknown"
GitCommit = "unknown"
)
// @title AIOps运维平台 API
// @version 1.0
// @description AIOps智能运维平台后端API文档
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:8080
// @BasePath /api/v1
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description Type "Bearer" followed by a space and JWT token.
func main() {
// 加载配置
cfg := config.Load()
// 初始化日志
log := logger.New(cfg.LogLevel)
defer log.Sync()
// 设置Gin模式
if cfg.Mode == "production" {
gin.SetMode(gin.ReleaseMode)
}
// 初始化数据库
db, err := database.New(cfg.Database)
if err != nil {
log.Fatal("failed to connect database", zap.Error(err))
}
// 自动迁移
if err := database.AutoMigrate(db); err != nil {
log.Fatal("failed to migrate database", zap.Error(err))
}
// 创建Gin实例
r := gin.New()
// 中间件
r.Use(gin.Recovery())
r.Use(logger.GinLogger(log))
r.Use(CORS())
// 版本信息 API
r.GET("/version", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"version": Version,
"build_time": BuildTime,
"git_commit": GitCommit,
})
})
// 注册路由
routes.Register(r, db, log, cfg)
// 创建HTTP服务器
srv := &http.Server{
Addr: ":" + cfg.Port,
Handler: r,
}
// 优雅关闭
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal("failed to start server", zap.Error(err))
}
}()
log.Info("server started", zap.String("port", cfg.Port))
// 等待中断信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Info("shutting down server...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("server forced to shutdown", zap.Error(err))
}
log.Info("server exited")
}
// CORS 跨域中间件
func CORS() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}