mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
186 lines
5.5 KiB
Go
186 lines
5.5 KiB
Go
// v16 is the first database migration after the V15 formal release baseline.
|
|
// It folds the previously drafted v16-v21 schema work into a single official
|
|
// upgrade: tunnel-relay fields, WAF IP groups, current node identity/version
|
|
// columns, and split node observation tables. The migration also backfills
|
|
// legacy node columns and removes obsolete pre-release tunnel metadata when
|
|
// present, so V15 deployments can upgrade directly to the new formal schema.
|
|
package migrate
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func (nodeV16) TableName() string {
|
|
return "nodes"
|
|
}
|
|
|
|
func (tunnelV16) TableName() string {
|
|
return "tunnels"
|
|
}
|
|
|
|
func (proxyRouteV16) TableName() string {
|
|
return "proxy_routes"
|
|
}
|
|
|
|
type nodeV16 struct{}
|
|
|
|
type tunnelV16 struct{}
|
|
|
|
type proxyRouteV16 struct{}
|
|
|
|
type wafIPGroupV16 struct{}
|
|
|
|
type wafRuleGroupV16 struct{}
|
|
|
|
func (wafIPGroupV16) TableName() string {
|
|
return "waf_ip_groups"
|
|
}
|
|
|
|
func (wafRuleGroupV16) TableName() string {
|
|
return "waf_rule_groups"
|
|
}
|
|
|
|
func init() {
|
|
Register(V16())
|
|
}
|
|
|
|
func V16() Migration {
|
|
return Migration{
|
|
FromVersion: 15,
|
|
ToVersion: 16,
|
|
Migrate: migrateV16,
|
|
Validate: validateV16,
|
|
}
|
|
}
|
|
|
|
func migrateV16(ctx Context, db *gorm.DB, backend string) error {
|
|
if err := ctx.ApplyCurrentSchema(db, backend); err != nil {
|
|
return err
|
|
}
|
|
|
|
migrator := db.Migrator()
|
|
if migrator.HasColumn(&nodeV16{}, "agent_token") {
|
|
if err := db.Exec(`UPDATE nodes SET access_token = agent_token WHERE access_token IS NULL OR access_token = ''`).Error; err != nil {
|
|
return fmt.Errorf("backfill nodes.access_token from agent_token: %w", err)
|
|
}
|
|
}
|
|
if migrator.HasColumn(&nodeV16{}, "agent_version") {
|
|
if err := db.Exec(`UPDATE nodes SET version = agent_version WHERE version = '' OR version IS NULL`).Error; err != nil {
|
|
return fmt.Errorf("backfill nodes.version from agent_version: %w", err)
|
|
}
|
|
}
|
|
if migrator.HasColumn(&nodeV16{}, "nginx_version") {
|
|
if err := db.Exec(`UPDATE nodes SET ext_version = nginx_version WHERE ext_version IS NULL OR ext_version = ''`).Error; err != nil {
|
|
return fmt.Errorf("backfill nodes.ext_version from nginx_version: %w", err)
|
|
}
|
|
}
|
|
if err := ctx.DropLegacyNodeColumns(db, backend); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := db.Exec("UPDATE nodes SET node_type = 'edge_node' WHERE node_type = '' OR node_type IS NULL").Error; err != nil {
|
|
return fmt.Errorf("backfill nodes.node_type: %w", err)
|
|
}
|
|
if err := db.Exec("UPDATE proxy_routes SET upstream_type = 'direct' WHERE upstream_type = '' OR upstream_type IS NULL").Error; err != nil {
|
|
return fmt.Errorf("backfill proxy_routes.upstream_type: %w", err)
|
|
}
|
|
|
|
if migrator.HasColumn(&proxyRouteV16{}, "tunnel_id") {
|
|
if err := db.Model(&proxyRouteV16{}).Where("upstream_type = ?", "tunnel").Update("upstream_type", "direct").Error; err != nil {
|
|
return fmt.Errorf("reset pre-release tunnel proxy routes: %w", err)
|
|
}
|
|
// Drop the legacy index idx_proxy_routes_tunnel_id if it exists, to avoid errors on dropping the tunnel_id column (especially on SQLite).
|
|
if migrator.HasIndex(&proxyRouteV16{}, "idx_proxy_routes_tunnel_id") {
|
|
if err := migrator.DropIndex(&proxyRouteV16{}, "idx_proxy_routes_tunnel_id"); err != nil {
|
|
return fmt.Errorf("drop index idx_proxy_routes_tunnel_id failed: %w", err)
|
|
}
|
|
}
|
|
if err := migrator.DropColumn(&proxyRouteV16{}, "tunnel_id"); err != nil {
|
|
return fmt.Errorf("drop pre-release proxy_routes.tunnel_id: %w", err)
|
|
}
|
|
}
|
|
if migrator.HasTable(&tunnelV16{}) {
|
|
if err := migrator.DropTable(&tunnelV16{}); err != nil {
|
|
return fmt.Errorf("drop pre-release tunnels table: %w", err)
|
|
}
|
|
slog.Info("dropped pre-release tunnels table during v16 migration")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func validateV16(ctx Context, db *gorm.DB, backend string) error {
|
|
if err := ctx.ValidateDatabaseSchemaVersion(db, backend, 15); err != nil {
|
|
return err
|
|
}
|
|
if db == nil {
|
|
return fmt.Errorf("database handle is nil")
|
|
}
|
|
|
|
migrator := db.Migrator()
|
|
for _, column := range []string{
|
|
"access_token",
|
|
"version",
|
|
"ext_version",
|
|
"node_type",
|
|
"relay_bind_port",
|
|
"relay_vhost_http_port",
|
|
"relay_auth_token",
|
|
"relay_agent_access_addr",
|
|
"relay_client_access_addr",
|
|
"relay_client_proxy_url",
|
|
"relay_status",
|
|
} {
|
|
if !migrator.HasColumn(&nodeV16{}, column) {
|
|
return fmt.Errorf("column nodes.%s is missing", column)
|
|
}
|
|
}
|
|
for _, column := range []string{
|
|
"upstream_type",
|
|
"tunnel_node_id",
|
|
"tunnel_target_addr",
|
|
"tunnel_target_protocol",
|
|
} {
|
|
if !migrator.HasColumn(&proxyRouteV16{}, column) {
|
|
return fmt.Errorf("column proxy_routes.%s is missing", column)
|
|
}
|
|
}
|
|
if migrator.HasColumn(&proxyRouteV16{}, "tunnel_id") {
|
|
return fmt.Errorf("column proxy_routes.tunnel_id should not exist in v16")
|
|
}
|
|
if migrator.HasTable(&tunnelV16{}) {
|
|
return fmt.Errorf("table tunnels should not exist in v16")
|
|
}
|
|
for _, column := range []string{
|
|
"agent_token",
|
|
"agent_version",
|
|
"nginx_version",
|
|
"relay_version",
|
|
"relay_frp_version",
|
|
"relay_frps_connections",
|
|
"relay_frps_proxy_count",
|
|
} {
|
|
if migrator.HasColumn(&nodeV16{}, column) {
|
|
return fmt.Errorf("column nodes.%s should not exist in v16", column)
|
|
}
|
|
}
|
|
if !migrator.HasTable(&wafIPGroupV16{}) {
|
|
return fmt.Errorf("table waf_ip_groups is missing")
|
|
}
|
|
for _, column := range []string{
|
|
"ip_whitelist_groups",
|
|
"ip_blacklist_groups",
|
|
} {
|
|
if !migrator.HasColumn(&wafRuleGroupV16{}, column) {
|
|
return fmt.Errorf("column waf_rule_groups.%s is missing", column)
|
|
}
|
|
}
|
|
if !migrator.HasColumn(&wafIPGroupV16{}, "ext_ips") {
|
|
return fmt.Errorf("column waf_ip_groups.ext_ips is missing")
|
|
}
|
|
return nil
|
|
}
|