mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-07 08:06:37 +08:00
[优化] 重构数据库迁移逻辑,添加版本管理和验证功能
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
package migrate
|
||||
|
||||
// Versions 1 through 7 are treated as the historical baseline. There are no
|
||||
// supported deployments below v8, so new upgrades start from this base version.
|
||||
@@ -0,0 +1,52 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const BaseDatabaseSchemaVersion = 7
|
||||
|
||||
type Context interface {
|
||||
ApplyCurrentSchema(db *gorm.DB, backend string) error
|
||||
BackfillOriginsFromProxyRoutes(db *gorm.DB) error
|
||||
BackfillProxyRouteSiteFields(db *gorm.DB) error
|
||||
EnsureProxyRouteSiteNameUniqueIndex(db *gorm.DB) error
|
||||
BackfillProxyRouteCertificateFields(db *gorm.DB) error
|
||||
BackfillProxyRouteDomainCertificateFields(db *gorm.DB) error
|
||||
EnsureDefaultGitHubAuthSource(db *gorm.DB) error
|
||||
EnsureDefaultWAFRuleGroup(db *gorm.DB) error
|
||||
ValidateDatabaseSchemaVersion(db *gorm.DB, backend string, version int) error
|
||||
}
|
||||
|
||||
type Migration struct {
|
||||
FromVersion int
|
||||
ToVersion int
|
||||
Migrate func(ctx Context, db *gorm.DB, backend string) error
|
||||
Validate func(ctx Context, db *gorm.DB, backend string) error
|
||||
}
|
||||
|
||||
var registeredMigrations []Migration
|
||||
|
||||
func Register(migration Migration) {
|
||||
registeredMigrations = append(registeredMigrations, migration)
|
||||
}
|
||||
|
||||
func Migrations() []Migration {
|
||||
migrations := append([]Migration{}, registeredMigrations...)
|
||||
sort.Slice(migrations, func(i int, j int) bool {
|
||||
return migrations[i].FromVersion < migrations[j].FromVersion
|
||||
})
|
||||
return migrations
|
||||
}
|
||||
|
||||
func CurrentVersion() int {
|
||||
version := BaseDatabaseSchemaVersion
|
||||
for _, migration := range registeredMigrations {
|
||||
if migration.ToVersion > version {
|
||||
version = migration.ToVersion
|
||||
}
|
||||
}
|
||||
return version
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package migrate
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMigrationsAreContinuousFromBaseVersion(t *testing.T) {
|
||||
migrations := Migrations()
|
||||
if len(migrations) == 0 {
|
||||
t.Fatal("expected at least one registered migration")
|
||||
}
|
||||
expectedFrom := BaseDatabaseSchemaVersion
|
||||
for _, migration := range migrations {
|
||||
if migration.FromVersion != expectedFrom {
|
||||
t.Fatalf("expected migration from v%d, got v%d -> v%d", expectedFrom, migration.FromVersion, migration.ToVersion)
|
||||
}
|
||||
if migration.ToVersion != migration.FromVersion+1 {
|
||||
t.Fatalf("expected one-step migration, got v%d -> v%d", migration.FromVersion, migration.ToVersion)
|
||||
}
|
||||
expectedFrom = migration.ToVersion
|
||||
}
|
||||
if CurrentVersion() != expectedFrom {
|
||||
t.Fatalf("unexpected current version: got %d want %d", CurrentVersion(), expectedFrom)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package migrate
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func init() {
|
||||
Register(V10())
|
||||
}
|
||||
|
||||
func V10() Migration {
|
||||
return Migration{
|
||||
FromVersion: 9,
|
||||
ToVersion: 10,
|
||||
Migrate: migrateV10,
|
||||
Validate: validateV10,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateV10(ctx Context, db *gorm.DB, backend string) error {
|
||||
if err := ctx.ApplyCurrentSchema(db, backend); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.EnsureDefaultGitHubAuthSource(db)
|
||||
}
|
||||
|
||||
func validateV10(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ValidateDatabaseSchemaVersion(db, backend, 10)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package migrate
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func init() {
|
||||
Register(V11())
|
||||
}
|
||||
|
||||
func V11() Migration {
|
||||
return Migration{
|
||||
FromVersion: 10,
|
||||
ToVersion: 11,
|
||||
Migrate: migrateV11,
|
||||
Validate: validateV11,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateV11(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ApplyCurrentSchema(db, backend)
|
||||
}
|
||||
|
||||
func validateV11(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ValidateDatabaseSchemaVersion(db, backend, 11)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package migrate
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func init() {
|
||||
Register(V12())
|
||||
}
|
||||
|
||||
func V12() Migration {
|
||||
return Migration{
|
||||
FromVersion: 11,
|
||||
ToVersion: 12,
|
||||
Migrate: migrateV12,
|
||||
Validate: validateV12,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateV12(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ApplyCurrentSchema(db, backend)
|
||||
}
|
||||
|
||||
func validateV12(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ValidateDatabaseSchemaVersion(db, backend, 12)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package migrate
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func init() {
|
||||
Register(V13())
|
||||
}
|
||||
|
||||
func V13() Migration {
|
||||
return Migration{
|
||||
FromVersion: 12,
|
||||
ToVersion: 13,
|
||||
Migrate: migrateV13,
|
||||
Validate: validateV13,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateV13(ctx Context, db *gorm.DB, backend string) error {
|
||||
if err := ctx.ApplyCurrentSchema(db, backend); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.EnsureDefaultWAFRuleGroup(db)
|
||||
}
|
||||
|
||||
func validateV13(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ValidateDatabaseSchemaVersion(db, backend, 13)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package migrate
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func init() {
|
||||
Register(V14())
|
||||
}
|
||||
|
||||
func V14() Migration {
|
||||
return Migration{
|
||||
FromVersion: 13,
|
||||
ToVersion: 14,
|
||||
Migrate: migrateV14,
|
||||
Validate: validateV14,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateV14(ctx Context, db *gorm.DB, backend string) error {
|
||||
if err := ctx.ApplyCurrentSchema(db, backend); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.EnsureDefaultWAFRuleGroup(db)
|
||||
}
|
||||
|
||||
func validateV14(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ValidateDatabaseSchemaVersion(db, backend, 14)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type nodeV15 struct {
|
||||
IPManualOverride bool `gorm:"column:ip_manual_override;not null;default:false"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register(V15())
|
||||
}
|
||||
|
||||
func V15() Migration {
|
||||
return Migration{
|
||||
FromVersion: 14,
|
||||
ToVersion: 15,
|
||||
Migrate: migrateV15,
|
||||
Validate: validateV15,
|
||||
}
|
||||
}
|
||||
|
||||
func (nodeV15) TableName() string {
|
||||
return "nodes"
|
||||
}
|
||||
|
||||
func migrateV15(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ApplyCurrentSchema(db, backend)
|
||||
}
|
||||
|
||||
func validateV15(ctx Context, db *gorm.DB, backend string) error {
|
||||
if err := ctx.ValidateDatabaseSchemaVersion(db, backend, 14); err != nil {
|
||||
return err
|
||||
}
|
||||
if db == nil || !db.Migrator().HasColumn(&nodeV15{}, "ip_manual_override") {
|
||||
return fmt.Errorf("column nodes.ip_manual_override is missing")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package migrate
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func init() {
|
||||
Register(V8())
|
||||
}
|
||||
|
||||
func V8() Migration {
|
||||
return Migration{
|
||||
FromVersion: 7,
|
||||
ToVersion: 8,
|
||||
Migrate: migrateV8,
|
||||
Validate: validateV8,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateV8(ctx Context, db *gorm.DB, backend string) error {
|
||||
if err := ctx.ApplyCurrentSchema(db, backend); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.BackfillOriginsFromProxyRoutes(db); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.BackfillProxyRouteSiteFields(db); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.EnsureProxyRouteSiteNameUniqueIndex(db); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.BackfillProxyRouteCertificateFields(db); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.BackfillProxyRouteDomainCertificateFields(db)
|
||||
}
|
||||
|
||||
func validateV8(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ValidateDatabaseSchemaVersion(db, backend, 8)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package migrate
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func init() {
|
||||
Register(V9())
|
||||
}
|
||||
|
||||
func V9() Migration {
|
||||
return Migration{
|
||||
FromVersion: 8,
|
||||
ToVersion: 9,
|
||||
Migrate: migrateV9,
|
||||
Validate: validateV9,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateV9(ctx Context, db *gorm.DB, backend string) error {
|
||||
if err := migrateV8(ctx, db, backend); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateV9(ctx Context, db *gorm.DB, backend string) error {
|
||||
return ctx.ValidateDatabaseSchemaVersion(db, backend, 9)
|
||||
}
|
||||
Reference in New Issue
Block a user