修复 DDNS ipv4 配置初次创建永远为 true 的问题

This commit is contained in:
dushixiang committed 2026-01-17 13:54:24 +08:00
1 parent 0788f1739f
commit a0e680b1c8
3 files changed
+128 -11

No files matched your search

+7
View File
@@ -5,6 +5,7 @@ import (
"strings"
"github.com/dushixiang/pika/internal/migrate/v0_1_1"
"github.com/dushixiang/pika/internal/migrate/v0_1_2"
"github.com/dushixiang/pika/internal/service"
"github.com/dushixiang/pika/pkg/version"
"go.uber.org/zap"
@@ -23,6 +24,12 @@ func AutoMigrate(logger *zap.Logger, db *gorm.DB, propertyService *service.Prope
return err
}
}
// 升级到 v0.1.2 版本
if strings.Compare(localVersion, "v0.1.2") < 0 {
if err := v0_1_2.Migrate(logger, db); err != nil {
return err
}
}
return propertyService.SetSystemVersion(ctx, version.Version)
}
+110
View File
@@ -0,0 +1,110 @@
package v0_1_2
import (
"strings"
"github.com/dushixiang/pika/internal/models"
"go.uber.org/zap"
"gorm.io/gorm"
)
func Migrate(logger *zap.Logger, db *gorm.DB) error {
// 移除 ddns_configs 表的 enable_ipv4,enable_ipv6 字段的默认值
logger.Info("开始执行 v0.1.2 版本数据迁移")
migrator := db.Migrator()
if migrator == nil {
logger.Warn("无法获取数据库 migrator,跳过迁移")
return nil
}
if !migrator.HasTable("ddns_configs") {
logger.Info("未检测到 ddns_configs 表,跳过迁移")
return nil
}
switch db.Dialector.Name() {
case "postgres":
if err := dropPostgresDefaults(logger, db, migrator); err != nil {
return err
}
case "sqlite":
if err := rebuildSQLiteDDNSConfigs(logger, db, migrator); err != nil {
return err
}
default:
logger.Warn("未知数据库类型,跳过移除默认值")
}
logger.Info("v0.1.2 版本数据迁移完成")
return nil
}
func dropPostgresDefaults(logger *zap.Logger, db *gorm.DB, migrator gorm.Migrator) error {
columns := []string{"enable_ipv4", "enable_ipv6"}
for _, column := range columns {
if !migrator.HasColumn("ddns_configs", column) {
logger.Info("未检测到字段,跳过处理", zap.String("column", column))
continue
}
sql := "ALTER TABLE ddns_configs ALTER COLUMN " + column + " DROP DEFAULT"
if err := db.Exec(sql).Error; err != nil {
logger.Error("移除字段默认值失败", zap.String("column", column), zap.Error(err))
return err
}
logger.Info("已移除字段默认值", zap.String("column", column))
}
return nil
}
func rebuildSQLiteDDNSConfigs(logger *zap.Logger, db *gorm.DB, migrator gorm.Migrator) error {
tempTable := "ddns_configs_backup_v0_1_2"
if migrator.HasTable(tempTable) {
logger.Warn("检测到残留备份表,跳过重建以避免覆盖", zap.String("table", tempTable))
return nil
}
logger.Info("SQLite 不支持直接删除默认值,开始重建 ddns_configs 表")
if err := db.Exec("ALTER TABLE ddns_configs RENAME TO " + tempTable).Error; err != nil {
logger.Error("重命名 ddns_configs 表失败", zap.Error(err))
return err
}
if err := db.AutoMigrate(&models.DDNSConfig{}); err != nil {
logger.Error("重建 ddns_configs 表失败", zap.Error(err))
return err
}
columns := []string{
"id",
"agent_id",
"name",
"enabled",
"provider",
"domains_ipv4",
"domains_ipv6",
"enable_ipv4",
"enable_ipv6",
"ipv4_get_method",
"ipv6_get_method",
"ipv4_get_value",
"ipv6_get_value",
"created_at",
"updated_at",
}
columnList := strings.Join(columns, ", ")
copySQL := "INSERT INTO ddns_configs (" + columnList + ") SELECT " + columnList + " FROM " + tempTable
if err := db.Exec(copySQL).Error; err != nil {
logger.Error("迁移 ddns_configs 数据失败", zap.Error(err))
return err
}
if err := migrator.DropTable(tempTable); err != nil {
logger.Error("删除备份表失败", zap.Error(err))
return err
}
logger.Info("ddns_configs 表重建完成")
return nil
}
+11 -11
View File
@@ -4,23 +4,23 @@ import "gorm.io/datatypes"
// DDNSConfig DDNS 配置
type DDNSConfig struct {
ID string `gorm:"primaryKey" json:"id"` // 配置ID (UUID)
AgentID string `gorm:"index" json:"agentId"` // 探针ID
Name string `json:"name"` // 配置名称
Enabled bool `gorm:"default:true" json:"enabled"` // 是否启用
Provider string `gorm:"index" json:"provider"` // DNS服务商类型: aliyun, tencentcloud, cloudflare, huaweicloud
ID string `gorm:"primaryKey" json:"id"` // 配置ID (UUID)
AgentID string `gorm:"index" json:"agentId"` // 探针ID
Name string `json:"name"` // 配置名称
Enabled bool `json:"enabled"` // 是否启用
Provider string `gorm:"index" json:"provider"` // DNS服务商类型: aliyun, tencentcloud, cloudflare, huaweicloud
// 域名配置(IPv4 和 IPv6 分开)
DomainsIPv4 datatypes.JSONSlice[string] `json:"domainsIpv4"` // IPv4 域名列表
DomainsIPv6 datatypes.JSONSlice[string] `json:"domainsIpv6"` // IPv6 域名列表
// IP 获取配置
EnableIPv4 bool `gorm:"default:true" json:"enableIpv4"` // 是否启用 IPv4
EnableIPv6 bool `gorm:"default:false" json:"enableIpv6"` // 是否启用 IPv6
IPv4GetMethod string `json:"ipv4GetMethod"` // IPv4 获取方式: api, interface
IPv6GetMethod string `json:"ipv6GetMethod"` // IPv6 获取方式: api, interface
IPv4GetValue string `json:"ipv4GetValue,omitempty"` // IPv4 获取配置值(接口名/API URL)
IPv6GetValue string `json:"ipv6GetValue,omitempty"` // IPv6 获取配置值(接口名/API URL)
EnableIPv4 bool `json:"enableIpv4"` // 是否启用 IPv4
EnableIPv6 bool `json:"enableIpv6"` // 是否启用 IPv6
IPv4GetMethod string `json:"ipv4GetMethod"` // IPv4 获取方式: api, interface
IPv6GetMethod string `json:"ipv6GetMethod"` // IPv6 获取方式: api, interface
IPv4GetValue string `json:"ipv4GetValue,omitempty"` // IPv4 获取配置值(接口名/API URL)
IPv6GetValue string `json:"ipv6GetValue,omitempty"` // IPv6 获取配置值(接口名/API URL)
CreatedAt int64 `json:"createdAt"` // 创建时间(时间戳毫秒)
UpdatedAt int64 `json:"updatedAt" gorm:"autoUpdateTime:milli"` // 更新时间(时间戳毫秒)