- 品牌: Go 模块/数据文件/二进制/构建部署资产全部 opsx→lokistack;前端 localStorage 命名空间迁移(读旧写新,含按用户 id 前缀迁移);修复 nginx upstream 与 Makefile 引用已改名服务的断裂 - i18n: react-i18next 落地,common + 11 个页面域命名空间全站中英(菜单/顶栏/登录/列表页/表单/确认弹窗/状态徽章);设置页语言即时切换;修复词典自注册导致的循环导入白屏 - 用户管理: 批量删除(POST /users/batch-delete,不删自己/最后管理员,部分失败不阻断)+ 行复选/全选/批量工具条 - 主题: 浅色侧栏(中性灰激活态)、四态模式(浅色/深色/跟随系统/定时切换,按时区判定)、顶栏太阳月亮二态、设置页紧凑分段选择器 - UI: 登录记住用户名、CardActionButton 统一五页卡片操作钮、shadcn Badge 替换手写徽章、语义色修正 - 清理: 移除主机 Web 终端(前后端)、k8s-helm/Helm 遗留代码与字段、README 重写精简 - 修复: 侧栏与日志告警 order 重复、路由标题 i18n key 未翻译、词典双逗号等
79 lines
2.3 KiB
Go
79 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"log"
|
|
"net/http"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"lokistack/config"
|
|
"lokistack/repository"
|
|
"lokistack/routers"
|
|
"lokistack/seed"
|
|
"lokistack/services"
|
|
)
|
|
|
|
func main() {
|
|
cfg := config.GetConfig()
|
|
|
|
log.Println("Initializing database...")
|
|
if err := repository.InitDB(); err != nil {
|
|
log.Fatalf("Failed to init DB: %v", err)
|
|
}
|
|
|
|
log.Println("Seeding default data...")
|
|
seed.Seed()
|
|
|
|
// 安全迁移:历史明文 kubeconfig → 加密存储,并清理明文文件
|
|
services.MigrateClusterKubeconfigs()
|
|
|
|
// 孤儿部署状态恢复:进程重启会杀掉进行中的部署 goroutine,
|
|
// 残留的 "deploying" 状态将永远卡住(UI 无停止入口),启动时统一标记为失败。
|
|
repository.GetDB().RecoverOrphanDeployments()
|
|
|
|
services.StartAlertEngine()
|
|
defer services.StopAlertEngine()
|
|
|
|
r := routers.SetupRouter()
|
|
srv := &http.Server{
|
|
Addr: ":" + cfg.ServerPort,
|
|
Handler: r,
|
|
ReadTimeout: 30 * time.Second,
|
|
WriteTimeout: 130 * time.Second,
|
|
IdleTimeout: 120 * time.Second,
|
|
}
|
|
|
|
// 监听中断/终止信号,实现优雅关停:先停 HTTP(拒绝新请求、处理完在途请求),
|
|
// 再 flush 数据库,避免防抖/异步保存丢失最近写入。
|
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
|
defer stop()
|
|
|
|
go func() {
|
|
log.Printf("lokistack starting on port %s", cfg.ServerPort)
|
|
log.Printf("API: http://localhost:%s/api/v1", cfg.ServerPort)
|
|
// 初始密码:首次启动日志中的「已生成管理员账号」,或数据卷 initial-admin-password.txt
|
|
log.Printf("首次部署请查看启动日志或 %s/initial-admin-password.txt 获取 admin 初始密码", cfg.DataDir)
|
|
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
log.Fatalf("Server failed: %v", err)
|
|
}
|
|
}()
|
|
|
|
<-ctx.Done()
|
|
log.Println("Shutdown signal received, draining connections...")
|
|
|
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer cancel()
|
|
if err := srv.Shutdown(shutdownCtx); err != nil {
|
|
log.Printf("HTTP shutdown error: %v", err)
|
|
}
|
|
|
|
log.Println("Flushing database...")
|
|
if err := repository.Shutdown(); err != nil {
|
|
log.Printf("DB shutdown error: %v", err)
|
|
}
|
|
log.Println("lokistack stopped")
|
|
}
|