center-config/transform/migrate.go

146 lines
4.1 KiB
Go

// Package transform ...
//
// Description : 数据迁移
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-30 3:57 下午
package transform
import (
"errors"
"fmt"
"git.zhangdeman.cn/zhangdeman/center-config/define/form"
"git.zhangdeman.cn/zhangdeman/center-config/define/model"
"git.zhangdeman.cn/zhangdeman/center-config/manager"
)
// MigrateOption 迁移的配置选项
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:41 下午 2021/11/30
type MigrateOption struct {
Force bool // 强制迁移
}
// SetMigrateOption 设置迁移选项
type SetMigrateOption func(mo *MigrateOption)
// WithOptionForce 配置是否强制迁移
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:43 下午 2021/11/30
func WithOptionForce(force bool) SetMigrateOption {
return func(mo *MigrateOption) {
mo.Force = force
}
}
// Migrate 数据迁移
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:58 下午 2021/11/30
func Migrate(dataDriver ITransform, optionList ...SetMigrateOption) error {
if nil == dataDriver {
return errors.New("data driver is nil")
}
namespace := dataDriver.GetNamespace()
if len(namespace) == 0 {
return errors.New("数据驱动器中, 未设置namespace")
}
mo := &MigrateOption{}
for _, o := range optionList {
o(mo)
}
var (
sourceData map[string]string
err error
namespaceDetail *model.Namespace
hasCreateConfigList []*model.Config
)
if sourceData, err = dataDriver.GetSourceData(); nil != err {
return err
}
namespaceID := int64(0)
if namespaceDetail, err = manager.Namespace.GetNamespaceDetail(0, namespace); nil == err && nil != namespaceDetail {
namespaceID = namespaceDetail.ID
if !mo.Force {
// 非强制迁移, 报错
return fmt.Errorf("当前命名空间 %s(%v) 已存在, 迁移存在风险, 若要强制迁移, 请使用force=true", namespace, namespaceDetail.ID)
}
// 强制迁移, 需要查询已有的key, 用于判断后续是
if hasCreateConfigList, err = manager.Config.GetNamespaceConfig(namespaceDetail.ID); nil != err {
return fmt.Errorf("当前命名空间 %s(%v) 已存在, 强制迁移查询已存在的配置失败: %s", namespace, namespaceDetail.ID, err.Error())
}
}
if namespaceID == 0 {
// 创建命名空间
if err = manager.Namespace.Create(&form.CreateNamespace{
Namespace: namespace,
Name: "apollo迁移-" + namespace,
Description: "从apollo迁移过来的配置",
CreateUserID: "migrate-script",
}); nil != err {
return errors.New("创建命名空间失败 : " + err.Error())
}
}
if nil != namespaceDetail && namespaceDetail.Status != model.NamespaceStatusNormal {
// 激活命名空间
if err = manager.Namespace.Active(&form.ActiveNamespace{
NamespaceID: 0,
Namespace: namespace,
UpdateUserID: "system-script",
}); nil != err {
return errors.New("激活命名空间失败 : " + err.Error())
}
}
hasCreateConfigTable := make(map[string]*model.Config)
for _, item := range hasCreateConfigList {
hasCreateConfigTable[item.Field] = item
}
// 迁移配置
for key, value := range sourceData {
hasSetConfig, exist := hasCreateConfigTable[key]
if !exist {
if err = manager.Config.Create(&form.CreateOrUpdateConfig{
NamespaceID: 0,
Namespace: namespace,
Key: key,
Value: value,
OperateUserID: "system-script",
Description: fmt.Sprintf("从apollo-%s-%s迁移过来的配置", namespace, key),
}, namespaceDetail); nil != err {
dataDriver.MigrateKeyFailCallback(namespace, key, value, err)
}
continue
}
// 已存在更新,执行下面的逻辑
if hasSetConfig.Value == value {
// 已存在值和目标值一致,无需处理
continue
}
if err = manager.Config.Update(&form.CreateOrUpdateConfig{
NamespaceID: namespaceDetail.ID,
Namespace: namespace,
Key: key,
Value: value,
OperateUserID: "system-script",
Description: fmt.Sprintf("从apollo-%s-%s迁移过来的配置", namespace, key),
}, namespaceDetail, hasSetConfig); nil != err {
dataDriver.MigrateKeyFailCallback(namespace, key, value, err)
}
}
return nil
}