Files
LokiStack/backend/repository/db_migrate_test.go
T
opsx cddd60045c
CI / Backend (go vet + test) (push) Canceled after 0s
CI / Frontend (lint + build + test) (push) Canceled after 0s
fix(db): 首次加载历史命名数据文件即迁移为 lokistack.json
旧回退链(lokistack.json → opsxloki.json → lokideploy.json)会永远沿用旧文件名,
旧品牌残留一直不消;现在首次从旧文件成功加载后立即原子写入 lokistack.json,
旧文件改名 .migrated-*.bak 留档(不删数据),新旧并存或写失败时退回旧路径安全运行。
2026-10-29 13:04:24 +08:00

58 lines
1.7 KiB
Go

package repository
import (
"os"
"path/filepath"
"strings"
"testing"
)
// TestMigrateLegacyDataFile 首次从历史命名(opsxloki.json)加载后必须升级到 lokistack.json:
// 新文件出现且内容完整,旧文件改名留档(不删数据)。
func TestMigrateLegacyDataFile(t *testing.T) {
dir := t.TempDir()
legacy := filepath.Join(dir, "opsxloki.json")
seed := `{"schemaVersion":10,"users":[{"id":1,"username":"admin"}],"clusters":[],"hosts":[],"storages":[],"deployments":[],"collectors":[],"logs":[],"settings":[],"logSources":[],"alertRules":[],"alertDeliveries":[],"notifyChannels":[],"logPolicyGroups":[],"auditLogs":[],"dailyVolumeSnapshots":[]}`
if err := os.WriteFile(legacy, []byte(seed), 0o600); err != nil {
t.Fatal(err)
}
d := &JsonDB{dataFile: legacy}
d.loadFromDisk()
d.migrateLegacyDataFile()
// 新文件存在且包含原有数据
content, err := os.ReadFile(filepath.Join(dir, "lokistack.json"))
if err != nil {
t.Fatalf("未生成 lokistack.json: %v", err)
}
if !strings.Contains(string(content), `"admin"`) {
t.Fatalf("迁移后数据不完整: %s", content[:min(len(content), 120)])
}
// 旧文件被改名留档,原内容不丢
entries, _ := os.ReadDir(dir)
backedUp := false
for _, e := range entries {
if strings.HasPrefix(e.Name(), "opsxloki.json.migrated-") {
kept, _ := os.ReadFile(filepath.Join(dir, e.Name()))
if string(kept) == seed {
backedUp = true
}
}
}
if !backedUp {
t.Fatalf("旧文件未留档或内容被改动: %v", entries)
}
// dataFile 已切到新路径
if filepath.Base(d.dataFile) != "lokistack.json" {
t.Fatalf("dataFile 未切换: %s", d.dataFile)
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}