[优化] 更新节点类型支持,添加隧道客户端,重构相关路由和配置

This commit is contained in:
ryan
2026-06-01 14:01:05 +08:00
parent a092935623
commit 6fa31cafc7
30 changed files with 317 additions and 1337 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ func registeredModels() []any {
&ProxyRoute{},
&ConfigVersion{},
&Node{},
&Tunnel{},
&NodeSystemProfile{},
&ApplyLog{},
&NodeMetricSnapshot{},
+82
View File
@@ -0,0 +1,82 @@
package migrate
import (
"fmt"
"log/slog"
"gorm.io/gorm"
)
type proxyRouteV19 struct {
ID uint `gorm:"primaryKey"`
TunnelID *uint `gorm:"column:tunnel_id"`
TunnelNodeID *uint `gorm:"column:tunnel_node_id"`
UpstreamType string `gorm:"column:upstream_type"`
}
func (proxyRouteV19) TableName() string {
return "proxy_routes"
}
func init() {
Register(V19())
}
func V19() Migration {
return Migration{
FromVersion: 18,
ToVersion: 19,
Migrate: migrateV19,
Validate: validateV19,
}
}
func migrateV19(ctx Context, db *gorm.DB, backend string) error {
// Drop tunnels table
if db.Migrator().HasTable("tunnels") {
if err := db.Migrator().DropTable("tunnels"); err != nil {
return fmt.Errorf("failed to drop tunnels table: %w", err)
}
slog.Info("dropped tunnels table")
}
// Add tunnel_node_id column
if !db.Migrator().HasColumn(&proxyRouteV19{}, "tunnel_node_id") {
if err := db.Migrator().AddColumn(&proxyRouteV19{}, "TunnelNodeID"); err != nil {
return fmt.Errorf("failed to add tunnel_node_id to proxy_routes: %w", err)
}
slog.Info("added tunnel_node_id column to proxy_routes")
}
// Drop old tunnel_id column
if db.Migrator().HasColumn(&proxyRouteV19{}, "tunnel_id") {
// Update routes that previously used tunnel to be disabled or direct to prevent dangling refs
db.Model(&proxyRouteV19{}).Where("upstream_type = ?", "tunnel").Update("upstream_type", "direct")
if err := db.Migrator().DropColumn(&proxyRouteV19{}, "tunnel_id"); err != nil {
return fmt.Errorf("failed to drop tunnel_id column from proxy_routes: %w", err)
}
slog.Info("dropped tunnel_id column from proxy_routes")
}
return ctx.ApplyCurrentSchema(db, backend)
}
func validateV19(ctx Context, db *gorm.DB, backend string) error {
if err := ctx.ValidateDatabaseSchemaVersion(db, backend, 18); err != nil {
return err
}
if db.Migrator().HasTable("tunnels") {
return fmt.Errorf("table tunnels should be dropped in v19")
}
if !db.Migrator().HasColumn(&proxyRouteV19{}, "tunnel_node_id") {
return fmt.Errorf("column proxy_routes.tunnel_node_id is missing")
}
if db.Migrator().HasColumn(&proxyRouteV19{}, "tunnel_id") {
return fmt.Errorf("column proxy_routes.tunnel_id should be dropped in v19")
}
return nil
}
+1 -1
View File
@@ -1164,7 +1164,7 @@ func validateDatabaseSchemaV16(db *gorm.DB, backend string) error {
if err := validateDatabaseSchemaV15(db, backend); err != nil {
return err
}
if !db.Migrator().HasTable(&Tunnel{}) {
if !db.Migrator().HasTable("tunnels") {
return fmt.Errorf("table tunnels is missing")
}
if !db.Migrator().HasColumn(&Node{}, "node_type") {
+2 -2
View File
@@ -31,7 +31,7 @@ type ProxyRoute struct {
BasicAuthPassword string `json:"basic_auth_password" gorm:"size:255;not null;default:''"`
Remark string `json:"remark" gorm:"size:255"`
UpstreamType string `json:"upstream_type" gorm:"size:32;not null;default:'direct'"`
TunnelID *uint `json:"tunnel_id" gorm:"index"`
TunnelNodeID *uint `json:"tunnel_node_id" gorm:"index"`
TunnelTargetAddr string `json:"tunnel_target_addr" gorm:"size:512"`
TunnelTargetProtocol string `json:"tunnel_target_protocol" gorm:"size:16"`
CreatedAt time.Time `json:"created_at"`
@@ -92,7 +92,7 @@ func (route *ProxyRoute) Update() error {
"basic_auth_password": route.BasicAuthPassword,
"remark": route.Remark,
"upstream_type": route.UpstreamType,
"tunnel_id": route.TunnelID,
"tunnel_node_id": route.TunnelNodeID,
"tunnel_target_addr": route.TunnelTargetAddr,
"tunnel_target_protocol": route.TunnelTargetProtocol,
}).Error
-56
View File
@@ -1,56 +0,0 @@
package model
import "time"
type Tunnel struct {
ID uint `json:"id" gorm:"primaryKey"`
TunnelID string `json:"tunnel_id" gorm:"uniqueIndex;size:64;not null"`
Name string `json:"name" gorm:"size:128;not null"`
TunnelToken string `json:"-" gorm:"size:128;index"`
Status string `json:"status" gorm:"size:16;not null;default:'offline'"`
ClientVersion string `json:"client_version" gorm:"size:64"`
FrpVersion string `json:"frp_version" gorm:"size:64"`
LastSeenAt time.Time `json:"last_seen_at"`
LastError string `json:"last_error" gorm:"type:text"`
CurrentVersion string `json:"current_version" gorm:"size:32"`
CurrentChecksum string `json:"current_checksum" gorm:"size:64"`
ConnectedRelays string `json:"connected_relays" gorm:"type:text;not null;default:'[]'"`
Remark string `json:"remark" gorm:"size:255"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func ListTunnels() (tunnels []*Tunnel, err error) {
err = DB.Order("id desc").Find(&tunnels).Error
return tunnels, err
}
func GetTunnelByID(id uint) (*Tunnel, error) {
tunnel := &Tunnel{}
err := DB.First(tunnel, id).Error
return tunnel, err
}
func GetTunnelByTunnelID(tunnelID string) (*Tunnel, error) {
tunnel := &Tunnel{}
err := DB.Where("tunnel_id = ?", tunnelID).First(tunnel).Error
return tunnel, err
}
func GetTunnelByTunnelToken(token string) (*Tunnel, error) {
tunnel := &Tunnel{}
err := DB.Where("tunnel_token = ?", token).First(tunnel).Error
return tunnel, err
}
func (tunnel *Tunnel) Insert() error {
return DB.Create(tunnel).Error
}
func (tunnel *Tunnel) Update() error {
return DB.Save(tunnel).Error
}
func (tunnel *Tunnel) Delete() error {
return DB.Delete(tunnel).Error
}