mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-09-04 23:16:41 +08:00
style(go): 统一后端代码格式
This commit is contained in:
@@ -95,4 +95,3 @@ func redirectStderr(path string) (func(), error) {
|
|||||||
_ = f.Close()
|
_ = f.Close()
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -357,4 +357,3 @@ func buildStorageRegistry() *storage.Registry {
|
|||||||
storageRclone.RegisterAllBackends(registry)
|
storageRclone.RegisterAllBackends(registry)
|
||||||
return registry
|
return registry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import (
|
|||||||
type Function string
|
type Function string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FunctionBackup Function = "backup"
|
FunctionBackup Function = "backup"
|
||||||
FunctionRestore Function = "restore"
|
FunctionRestore Function = "restore"
|
||||||
FunctionInquire Function = "inquire"
|
FunctionInquire Function = "inquire"
|
||||||
FunctionDelete Function = "delete"
|
FunctionDelete Function = "delete"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BackupRequest 是 BACKUP 操作的单条请求。
|
// BackupRequest 是 BACKUP 操作的单条请求。
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ func TestFileRunnerSelectiveRestore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
diffAssertContent(t, filepath.Join(restoreSrc, "a.txt"), "alpha")
|
diffAssertContent(t, filepath.Join(restoreSrc, "a.txt"), "alpha")
|
||||||
diffAssertContent(t, filepath.Join(restoreSrc, "sub", "c.txt"), "charlie") // 选中目录 → 子项一并恢复
|
diffAssertContent(t, filepath.Join(restoreSrc, "sub", "c.txt"), "charlie") // 选中目录 → 子项一并恢复
|
||||||
diffAssertAbsent(t, filepath.Join(restoreSrc, "b.txt")) // 未选中 → 不恢复
|
diffAssertAbsent(t, filepath.Join(restoreSrc, "b.txt")) // 未选中 → 不恢复
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFileRunnerDifferentialWithoutBaseIsFull 验证无基线时差异请求回退为全量(产出清单、含全部文件)。
|
// TestFileRunnerDifferentialWithoutBaseIsFull 验证无基线时差异请求回退为全量(产出清单、含全部文件)。
|
||||||
|
|||||||
@@ -160,4 +160,3 @@ func formatFileSize(size int64) string {
|
|||||||
return fmt.Sprintf("%d B", size)
|
return fmt.Sprintf("%d B", size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ func writeTestTar(t *testing.T, entries map[string][]byte) string {
|
|||||||
|
|
||||||
func TestVerifyTarArchive_Valid(t *testing.T) {
|
func TestVerifyTarArchive_Valid(t *testing.T) {
|
||||||
path := writeTestTar(t, map[string][]byte{
|
path := writeTestTar(t, map[string][]byte{
|
||||||
"readme.md": []byte("hello"),
|
"readme.md": []byte("hello"),
|
||||||
"data.bin": []byte("world!!!"),
|
"data.bin": []byte("world!!!"),
|
||||||
})
|
})
|
||||||
report, err := VerifyTarArchive(path, "")
|
report, err := VerifyTarArchive(path, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ type MaintenanceWindow struct {
|
|||||||
// 简化语法:多个窗口以 ';' 分隔,每个窗口按 "[days=xxx;]time=HH:MM-HH:MM" 格式。
|
// 简化语法:多个窗口以 ';' 分隔,每个窗口按 "[days=xxx;]time=HH:MM-HH:MM" 格式。
|
||||||
// Days 缺省 = 全周;若不合法,跳过该段而非抛错(让调用方尽力工作)。
|
// Days 缺省 = 全周;若不合法,跳过该段而非抛错(让调用方尽力工作)。
|
||||||
// 示例:
|
// 示例:
|
||||||
// "time=01:00-05:00" 每天 1 点到 5 点
|
//
|
||||||
// "days=sat,sun;time=00:00-23:59" 仅周末全天
|
// "time=01:00-05:00" 每天 1 点到 5 点
|
||||||
// "time=22:00-06:00" 每天跨夜
|
// "days=sat,sun;time=00:00-23:59" 仅周末全天
|
||||||
// "days=mon,tue,wed,thu,fri;time=22:00-06:00" 工作日跨夜
|
// "time=22:00-06:00" 每天跨夜
|
||||||
|
// "days=mon,tue,wed,thu,fri;time=22:00-06:00" 工作日跨夜
|
||||||
func ParseMaintenanceWindows(value string) []MaintenanceWindow {
|
func ParseMaintenanceWindows(value string) []MaintenanceWindow {
|
||||||
v := strings.TrimSpace(value)
|
v := strings.TrimSpace(value)
|
||||||
if v == "" {
|
if v == "" {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import "time"
|
|||||||
// 任一 Notification 可订阅多个事件,EventTypes 字段存 CSV。
|
// 任一 Notification 可订阅多个事件,EventTypes 字段存 CSV。
|
||||||
// 空 EventTypes + OnSuccess/OnFailure=true 时沿用旧语义(仅备份成功/失败)。
|
// 空 EventTypes + OnSuccess/OnFailure=true 时沿用旧语义(仅备份成功/失败)。
|
||||||
const (
|
const (
|
||||||
NotificationEventBackupSuccess = "backup_success"
|
NotificationEventBackupSuccess = "backup_success"
|
||||||
NotificationEventBackupFailed = "backup_failed"
|
NotificationEventBackupFailed = "backup_failed"
|
||||||
NotificationEventRestoreSuccess = "restore_success"
|
NotificationEventRestoreSuccess = "restore_success"
|
||||||
NotificationEventRestoreFailed = "restore_failed"
|
NotificationEventRestoreFailed = "restore_failed"
|
||||||
NotificationEventVerifyFailed = "verify_failed"
|
NotificationEventVerifyFailed = "verify_failed"
|
||||||
NotificationEventSLAViolation = "sla_violation"
|
NotificationEventSLAViolation = "sla_violation"
|
||||||
// NotificationEventStorageUnhealthy 存储目标连接失败(后台健康扫描触发)。
|
// NotificationEventStorageUnhealthy 存储目标连接失败(后台健康扫描触发)。
|
||||||
NotificationEventStorageUnhealthy = "storage_unhealthy"
|
NotificationEventStorageUnhealthy = "storage_unhealthy"
|
||||||
// NotificationEventReplicationFailed 备份复制失败。
|
// NotificationEventReplicationFailed 备份复制失败。
|
||||||
@@ -23,13 +23,13 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
ID uint `gorm:"primaryKey" json:"id"`
|
ID uint `gorm:"primaryKey" json:"id"`
|
||||||
Type string `gorm:"size:20;index;not null" json:"type"`
|
Type string `gorm:"size:20;index;not null" json:"type"`
|
||||||
Name string `gorm:"size:100;uniqueIndex;not null" json:"name"`
|
Name string `gorm:"size:100;uniqueIndex;not null" json:"name"`
|
||||||
ConfigCiphertext string `gorm:"column:config_ciphertext;type:text;not null" json:"-"`
|
ConfigCiphertext string `gorm:"column:config_ciphertext;type:text;not null" json:"-"`
|
||||||
Enabled bool `gorm:"not null;default:true" json:"enabled"`
|
Enabled bool `gorm:"not null;default:true" json:"enabled"`
|
||||||
OnSuccess bool `gorm:"column:on_success;not null;default:false" json:"onSuccess"`
|
OnSuccess bool `gorm:"column:on_success;not null;default:false" json:"onSuccess"`
|
||||||
OnFailure bool `gorm:"column:on_failure;not null;default:true" json:"onFailure"`
|
OnFailure bool `gorm:"column:on_failure;not null;default:true" json:"onFailure"`
|
||||||
// EventTypes 逗号分隔,订阅的事件类型。
|
// EventTypes 逗号分隔,订阅的事件类型。
|
||||||
// 空 = 仅监听备份成功/失败(兼容旧配置);非空则严格按订阅触发。
|
// 空 = 仅监听备份成功/失败(兼容旧配置);非空则严格按订阅触发。
|
||||||
EventTypes string `gorm:"column:event_types;size:500" json:"eventTypes"`
|
EventTypes string `gorm:"column:event_types;size:500" json:"eventTypes"`
|
||||||
|
|||||||
@@ -24,19 +24,19 @@ type ReplicationRecord struct {
|
|||||||
SourceTargetID uint `gorm:"column:source_target_id;index;not null" json:"sourceTargetId"`
|
SourceTargetID uint `gorm:"column:source_target_id;index;not null" json:"sourceTargetId"`
|
||||||
SourceTarget StorageTarget `gorm:"foreignKey:SourceTargetID;references:ID" json:"sourceTarget,omitempty"`
|
SourceTarget StorageTarget `gorm:"foreignKey:SourceTargetID;references:ID" json:"sourceTarget,omitempty"`
|
||||||
// DestTargetID 目标存储(复制过去)
|
// DestTargetID 目标存储(复制过去)
|
||||||
DestTargetID uint `gorm:"column:dest_target_id;index;not null" json:"destTargetId"`
|
DestTargetID uint `gorm:"column:dest_target_id;index;not null" json:"destTargetId"`
|
||||||
DestTarget StorageTarget `gorm:"foreignKey:DestTargetID;references:ID" json:"destTarget,omitempty"`
|
DestTarget StorageTarget `gorm:"foreignKey:DestTargetID;references:ID" json:"destTarget,omitempty"`
|
||||||
Status string `gorm:"size:20;index;not null" json:"status"`
|
Status string `gorm:"size:20;index;not null" json:"status"`
|
||||||
StoragePath string `gorm:"column:storage_path;size:500" json:"storagePath"`
|
StoragePath string `gorm:"column:storage_path;size:500" json:"storagePath"`
|
||||||
FileSize int64 `gorm:"column:file_size;not null;default:0" json:"fileSize"`
|
FileSize int64 `gorm:"column:file_size;not null;default:0" json:"fileSize"`
|
||||||
Checksum string `gorm:"column:checksum;size:64" json:"checksum"`
|
Checksum string `gorm:"column:checksum;size:64" json:"checksum"`
|
||||||
ErrorMessage string `gorm:"column:error_message;size:2000" json:"errorMessage"`
|
ErrorMessage string `gorm:"column:error_message;size:2000" json:"errorMessage"`
|
||||||
DurationSeconds int `gorm:"column:duration_seconds;not null;default:0" json:"durationSeconds"`
|
DurationSeconds int `gorm:"column:duration_seconds;not null;default:0" json:"durationSeconds"`
|
||||||
TriggeredBy string `gorm:"column:triggered_by;size:100" json:"triggeredBy"`
|
TriggeredBy string `gorm:"column:triggered_by;size:100" json:"triggeredBy"`
|
||||||
StartedAt time.Time `gorm:"column:started_at;index;not null" json:"startedAt"`
|
StartedAt time.Time `gorm:"column:started_at;index;not null" json:"startedAt"`
|
||||||
CompletedAt *time.Time `gorm:"column:completed_at;index" json:"completedAt,omitempty"`
|
CompletedAt *time.Time `gorm:"column:completed_at;index" json:"completedAt,omitempty"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ReplicationRecord) TableName() string {
|
func (ReplicationRecord) TableName() string {
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import "time"
|
|||||||
// - name
|
// - name
|
||||||
// - sourcePath / sourcePaths 中的 {{.Host}} / {{.Env}} 等占位符
|
// - sourcePath / sourcePaths 中的 {{.Host}} / {{.Env}} 等占位符
|
||||||
type TaskTemplate struct {
|
type TaskTemplate struct {
|
||||||
ID uint `gorm:"primaryKey" json:"id"`
|
ID uint `gorm:"primaryKey" json:"id"`
|
||||||
Name string `gorm:"size:128;uniqueIndex;not null" json:"name"`
|
Name string `gorm:"size:128;uniqueIndex;not null" json:"name"`
|
||||||
Description string `gorm:"size:500" json:"description"`
|
Description string `gorm:"size:500" json:"description"`
|
||||||
TaskType string `gorm:"column:task_type;size:20;not null" json:"taskType"`
|
TaskType string `gorm:"column:task_type;size:20;not null" json:"taskType"`
|
||||||
// Payload JSON,存完整 BackupTaskUpsertInput 的序列化
|
// Payload JSON,存完整 BackupTaskUpsertInput 的序列化
|
||||||
Payload string `gorm:"type:text;not null" json:"payload"`
|
Payload string `gorm:"type:text;not null" json:"payload"`
|
||||||
CreatedBy string `gorm:"column:created_by;size:128" json:"createdBy"`
|
CreatedBy string `gorm:"column:created_by;size:128" json:"createdBy"`
|
||||||
|
|||||||
@@ -126,14 +126,14 @@ func (s *DashboardService) Timeline(ctx context.Context, days int) ([]repository
|
|||||||
// 判定规则:任务设置了 SLAHoursRPO > 0,且距最近一次 success 备份的时间 > SLAHoursRPO。
|
// 判定规则:任务设置了 SLAHoursRPO > 0,且距最近一次 success 备份的时间 > SLAHoursRPO。
|
||||||
// 从未成功过的任务(LastSuccessAt = nil)若启用也视为违约(from createdAt 起算)。
|
// 从未成功过的任务(LastSuccessAt = nil)若启用也视为违约(from createdAt 起算)。
|
||||||
type SLAViolation struct {
|
type SLAViolation struct {
|
||||||
TaskID uint `json:"taskId"`
|
TaskID uint `json:"taskId"`
|
||||||
TaskName string `json:"taskName"`
|
TaskName string `json:"taskName"`
|
||||||
NodeID uint `json:"nodeId"`
|
NodeID uint `json:"nodeId"`
|
||||||
NodeName string `json:"nodeName,omitempty"`
|
NodeName string `json:"nodeName,omitempty"`
|
||||||
SLAHoursRPO int `json:"slaHoursRpo"`
|
SLAHoursRPO int `json:"slaHoursRpo"`
|
||||||
LastSuccessAt *time.Time `json:"lastSuccessAt,omitempty"`
|
LastSuccessAt *time.Time `json:"lastSuccessAt,omitempty"`
|
||||||
HoursSinceLastSuccess float64 `json:"hoursSinceLastSuccess"`
|
HoursSinceLastSuccess float64 `json:"hoursSinceLastSuccess"`
|
||||||
NeverSucceeded bool `json:"neverSucceeded"`
|
NeverSucceeded bool `json:"neverSucceeded"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SLAComplianceReport Dashboard 的 SLA 合规概览。
|
// SLAComplianceReport Dashboard 的 SLA 合规概览。
|
||||||
@@ -204,15 +204,15 @@ func roundHours(value float64) float64 {
|
|||||||
|
|
||||||
// ClusterNodeSummary 集群节点简报(Dashboard 用)。
|
// ClusterNodeSummary 集群节点简报(Dashboard 用)。
|
||||||
type ClusterNodeSummary struct {
|
type ClusterNodeSummary struct {
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
IsLocal bool `json:"isLocal"`
|
IsLocal bool `json:"isLocal"`
|
||||||
AgentVersion string `json:"agentVersion"`
|
AgentVersion string `json:"agentVersion"`
|
||||||
VersionStatus string `json:"versionStatus"` // current | outdated | unknown
|
VersionStatus string `json:"versionStatus"` // current | outdated | unknown
|
||||||
LastSeen time.Time `json:"lastSeen"`
|
LastSeen time.Time `json:"lastSeen"`
|
||||||
TaskCount int64 `json:"taskCount"`
|
TaskCount int64 `json:"taskCount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClusterOverview Dashboard 集群概览卡片。
|
// ClusterOverview Dashboard 集群概览卡片。
|
||||||
@@ -312,9 +312,9 @@ func (s *DashboardService) Breakdown(ctx context.Context, days int) (*BreakdownS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result := &BreakdownStats{
|
result := &BreakdownStats{
|
||||||
ByType: makeBreakdown(typeCounts, typeLabel),
|
ByType: makeBreakdown(typeCounts, typeLabel),
|
||||||
ByNode: makeBreakdownByUint(nodeCounts, nodeNames, "节点 #"),
|
ByNode: makeBreakdownByUint(nodeCounts, nodeNames, "节点 #"),
|
||||||
ByStatus: []BreakdownItem{},
|
ByStatus: []BreakdownItem{},
|
||||||
ByStorage: []BreakdownItem{},
|
ByStorage: []BreakdownItem{},
|
||||||
}
|
}
|
||||||
// 按状态(最近 days 天记录)
|
// 按状态(最近 days 天记录)
|
||||||
|
|||||||
@@ -74,11 +74,11 @@ func (s *SystemService) CheckUpdate(ctx context.Context) (*UpdateCheckResult, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
var release struct {
|
var release struct {
|
||||||
TagName string `json:"tag_name"`
|
TagName string `json:"tag_name"`
|
||||||
HTMLURL string `json:"html_url"`
|
HTMLURL string `json:"html_url"`
|
||||||
Body string `json:"body"`
|
Body string `json:"body"`
|
||||||
Published string `json:"published_at"`
|
Published string `json:"published_at"`
|
||||||
Assets []struct {
|
Assets []struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
BrowserDownloadURL string `json:"browser_download_url"`
|
BrowserDownloadURL string `json:"browser_download_url"`
|
||||||
} `json:"assets"`
|
} `json:"assets"`
|
||||||
@@ -132,4 +132,3 @@ func (s *SystemService) GetInfo(_ context.Context) *SystemInfo {
|
|||||||
}
|
}
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import (
|
|||||||
|
|
||||||
// TaskExportService 管理备份任务的 JSON 导入 / 导出。
|
// TaskExportService 管理备份任务的 JSON 导入 / 导出。
|
||||||
// 用途:
|
// 用途:
|
||||||
// 1. 集群迁移(旧 Master → 新 Master 的任务配置搬迁)
|
// 1. 集群迁移(旧 Master → 新 Master 的任务配置搬迁)
|
||||||
// 2. 灾备恢复(任务配置本地文件化,Master 宕机后重建)
|
// 2. 灾备恢复(任务配置本地文件化,Master 宕机后重建)
|
||||||
// 3. 配置审计(版本化 Git 管理 JSON 快照)
|
// 3. 配置审计(版本化 Git 管理 JSON 快照)
|
||||||
//
|
//
|
||||||
// 出于安全考虑,导出/导入不包含任何敏感字段:
|
// 出于安全考虑,导出/导入不包含任何敏感字段:
|
||||||
// - 数据库密码(DBPasswordCiphertext):跳过,导入后需人工填补
|
// - 数据库密码(DBPasswordCiphertext):跳过,导入后需人工填补
|
||||||
@@ -40,35 +40,35 @@ func NewTaskExportService(
|
|||||||
|
|
||||||
// ExportedTask 导出格式:按名称引用存储/节点,不含敏感数据。
|
// ExportedTask 导出格式:按名称引用存储/节点,不含敏感数据。
|
||||||
type ExportedTask struct {
|
type ExportedTask struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
CronExpr string `json:"cronExpr,omitempty"`
|
CronExpr string `json:"cronExpr,omitempty"`
|
||||||
SourcePath string `json:"sourcePath,omitempty"`
|
SourcePath string `json:"sourcePath,omitempty"`
|
||||||
SourcePaths []string `json:"sourcePaths,omitempty"`
|
SourcePaths []string `json:"sourcePaths,omitempty"`
|
||||||
ExcludePatterns []string `json:"excludePatterns,omitempty"`
|
ExcludePatterns []string `json:"excludePatterns,omitempty"`
|
||||||
DBHost string `json:"dbHost,omitempty"`
|
DBHost string `json:"dbHost,omitempty"`
|
||||||
DBPort int `json:"dbPort,omitempty"`
|
DBPort int `json:"dbPort,omitempty"`
|
||||||
DBUser string `json:"dbUser,omitempty"`
|
DBUser string `json:"dbUser,omitempty"`
|
||||||
DBName string `json:"dbName,omitempty"`
|
DBName string `json:"dbName,omitempty"`
|
||||||
DBPath string `json:"dbPath,omitempty"`
|
DBPath string `json:"dbPath,omitempty"`
|
||||||
ExtraConfig map[string]any `json:"extraConfig,omitempty"`
|
ExtraConfig map[string]any `json:"extraConfig,omitempty"`
|
||||||
// 按名称引用:导入时按名称查找对应 ID
|
// 按名称引用:导入时按名称查找对应 ID
|
||||||
StorageTargetNames []string `json:"storageTargetNames"`
|
StorageTargetNames []string `json:"storageTargetNames"`
|
||||||
ReplicationTargetNames []string `json:"replicationTargetNames,omitempty"`
|
ReplicationTargetNames []string `json:"replicationTargetNames,omitempty"`
|
||||||
NodeName string `json:"nodeName,omitempty"`
|
NodeName string `json:"nodeName,omitempty"`
|
||||||
DependsOnTaskNames []string `json:"dependsOnTaskNames,omitempty"`
|
DependsOnTaskNames []string `json:"dependsOnTaskNames,omitempty"`
|
||||||
Tags string `json:"tags,omitempty"`
|
Tags string `json:"tags,omitempty"`
|
||||||
Compression string `json:"compression,omitempty"`
|
Compression string `json:"compression,omitempty"`
|
||||||
Encrypt bool `json:"encrypt,omitempty"`
|
Encrypt bool `json:"encrypt,omitempty"`
|
||||||
RetentionDays int `json:"retentionDays,omitempty"`
|
RetentionDays int `json:"retentionDays,omitempty"`
|
||||||
MaxBackups int `json:"maxBackups,omitempty"`
|
MaxBackups int `json:"maxBackups,omitempty"`
|
||||||
VerifyEnabled bool `json:"verifyEnabled,omitempty"`
|
VerifyEnabled bool `json:"verifyEnabled,omitempty"`
|
||||||
VerifyCronExpr string `json:"verifyCronExpr,omitempty"`
|
VerifyCronExpr string `json:"verifyCronExpr,omitempty"`
|
||||||
VerifyMode string `json:"verifyMode,omitempty"`
|
VerifyMode string `json:"verifyMode,omitempty"`
|
||||||
SLAHoursRPO int `json:"slaHoursRpo,omitempty"`
|
SLAHoursRPO int `json:"slaHoursRpo,omitempty"`
|
||||||
AlertOnConsecutiveFails int `json:"alertOnConsecutiveFails,omitempty"`
|
AlertOnConsecutiveFails int `json:"alertOnConsecutiveFails,omitempty"`
|
||||||
MaintenanceWindows string `json:"maintenanceWindows,omitempty"`
|
MaintenanceWindows string `json:"maintenanceWindows,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportPayload 导出整体结构,带元信息。
|
// ExportPayload 导出整体结构,带元信息。
|
||||||
@@ -233,67 +233,67 @@ func (s *TaskExportService) toExported(item *model.BackupTask, targetNames, node
|
|||||||
nodeName = nodeNames[item.NodeID]
|
nodeName = nodeNames[item.NodeID]
|
||||||
}
|
}
|
||||||
return ExportedTask{
|
return ExportedTask{
|
||||||
Name: item.Name,
|
Name: item.Name,
|
||||||
Type: item.Type,
|
Type: item.Type,
|
||||||
Enabled: item.Enabled,
|
Enabled: item.Enabled,
|
||||||
CronExpr: item.CronExpr,
|
CronExpr: item.CronExpr,
|
||||||
SourcePath: item.SourcePath,
|
SourcePath: item.SourcePath,
|
||||||
SourcePaths: sourcePaths,
|
SourcePaths: sourcePaths,
|
||||||
ExcludePatterns: excludes,
|
ExcludePatterns: excludes,
|
||||||
DBHost: item.DBHost,
|
DBHost: item.DBHost,
|
||||||
DBPort: item.DBPort,
|
DBPort: item.DBPort,
|
||||||
DBUser: item.DBUser,
|
DBUser: item.DBUser,
|
||||||
DBName: item.DBName,
|
DBName: item.DBName,
|
||||||
DBPath: item.DBPath,
|
DBPath: item.DBPath,
|
||||||
ExtraConfig: extra,
|
ExtraConfig: extra,
|
||||||
StorageTargetNames: storageNames,
|
StorageTargetNames: storageNames,
|
||||||
ReplicationTargetNames: replicationNames,
|
ReplicationTargetNames: replicationNames,
|
||||||
NodeName: nodeName,
|
NodeName: nodeName,
|
||||||
DependsOnTaskNames: dependsOnNames,
|
DependsOnTaskNames: dependsOnNames,
|
||||||
Tags: item.Tags,
|
Tags: item.Tags,
|
||||||
Compression: item.Compression,
|
Compression: item.Compression,
|
||||||
Encrypt: item.Encrypt,
|
Encrypt: item.Encrypt,
|
||||||
RetentionDays: item.RetentionDays,
|
RetentionDays: item.RetentionDays,
|
||||||
MaxBackups: item.MaxBackups,
|
MaxBackups: item.MaxBackups,
|
||||||
VerifyEnabled: item.VerifyEnabled,
|
VerifyEnabled: item.VerifyEnabled,
|
||||||
VerifyCronExpr: item.VerifyCronExpr,
|
VerifyCronExpr: item.VerifyCronExpr,
|
||||||
VerifyMode: item.VerifyMode,
|
VerifyMode: item.VerifyMode,
|
||||||
SLAHoursRPO: item.SLAHoursRPO,
|
SLAHoursRPO: item.SLAHoursRPO,
|
||||||
AlertOnConsecutiveFails: item.AlertOnConsecutiveFails,
|
AlertOnConsecutiveFails: item.AlertOnConsecutiveFails,
|
||||||
MaintenanceWindows: item.MaintenanceWindows,
|
MaintenanceWindows: item.MaintenanceWindows,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TaskExportService) toUpsertInput(t ExportedTask, targetsByName, nodesByName map[string]uint, deps []uint) BackupTaskUpsertInput {
|
func (s *TaskExportService) toUpsertInput(t ExportedTask, targetsByName, nodesByName map[string]uint, deps []uint) BackupTaskUpsertInput {
|
||||||
return BackupTaskUpsertInput{
|
return BackupTaskUpsertInput{
|
||||||
Name: t.Name,
|
Name: t.Name,
|
||||||
Type: t.Type,
|
Type: t.Type,
|
||||||
Enabled: t.Enabled,
|
Enabled: t.Enabled,
|
||||||
CronExpr: t.CronExpr,
|
CronExpr: t.CronExpr,
|
||||||
SourcePath: t.SourcePath,
|
SourcePath: t.SourcePath,
|
||||||
SourcePaths: t.SourcePaths,
|
SourcePaths: t.SourcePaths,
|
||||||
ExcludePatterns: t.ExcludePatterns,
|
ExcludePatterns: t.ExcludePatterns,
|
||||||
DBHost: t.DBHost,
|
DBHost: t.DBHost,
|
||||||
DBPort: t.DBPort,
|
DBPort: t.DBPort,
|
||||||
DBUser: t.DBUser,
|
DBUser: t.DBUser,
|
||||||
DBName: t.DBName,
|
DBName: t.DBName,
|
||||||
DBPath: t.DBPath,
|
DBPath: t.DBPath,
|
||||||
ExtraConfig: t.ExtraConfig,
|
ExtraConfig: t.ExtraConfig,
|
||||||
StorageTargetIDs: idsFromNames(t.StorageTargetNames, targetsByName),
|
StorageTargetIDs: idsFromNames(t.StorageTargetNames, targetsByName),
|
||||||
ReplicationTargetIDs: idsFromNames(t.ReplicationTargetNames, targetsByName),
|
ReplicationTargetIDs: idsFromNames(t.ReplicationTargetNames, targetsByName),
|
||||||
NodeID: nodesByName[t.NodeName],
|
NodeID: nodesByName[t.NodeName],
|
||||||
Tags: t.Tags,
|
Tags: t.Tags,
|
||||||
Compression: t.Compression,
|
Compression: t.Compression,
|
||||||
Encrypt: t.Encrypt,
|
Encrypt: t.Encrypt,
|
||||||
RetentionDays: t.RetentionDays,
|
RetentionDays: t.RetentionDays,
|
||||||
MaxBackups: t.MaxBackups,
|
MaxBackups: t.MaxBackups,
|
||||||
VerifyEnabled: t.VerifyEnabled,
|
VerifyEnabled: t.VerifyEnabled,
|
||||||
VerifyCronExpr: t.VerifyCronExpr,
|
VerifyCronExpr: t.VerifyCronExpr,
|
||||||
VerifyMode: t.VerifyMode,
|
VerifyMode: t.VerifyMode,
|
||||||
SLAHoursRPO: t.SLAHoursRPO,
|
SLAHoursRPO: t.SLAHoursRPO,
|
||||||
AlertOnConsecutiveFails: t.AlertOnConsecutiveFails,
|
AlertOnConsecutiveFails: t.AlertOnConsecutiveFails,
|
||||||
MaintenanceWindows: t.MaintenanceWindows,
|
MaintenanceWindows: t.MaintenanceWindows,
|
||||||
DependsOnTaskIDs: deps,
|
DependsOnTaskIDs: deps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type LocalDiskFactory struct{}
|
|||||||
func NewLocalDiskFactory() LocalDiskFactory { return LocalDiskFactory{} }
|
func NewLocalDiskFactory() LocalDiskFactory { return LocalDiskFactory{} }
|
||||||
|
|
||||||
func (LocalDiskFactory) Type() storage.ProviderType { return storage.ProviderTypeLocalDisk }
|
func (LocalDiskFactory) Type() storage.ProviderType { return storage.ProviderTypeLocalDisk }
|
||||||
func (LocalDiskFactory) SensitiveFields() []string { return nil }
|
func (LocalDiskFactory) SensitiveFields() []string { return nil }
|
||||||
|
|
||||||
func (LocalDiskFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
func (LocalDiskFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
||||||
cfg, err := storage.DecodeConfig[storage.LocalDiskConfig](rawConfig)
|
cfg, err := storage.DecodeConfig[storage.LocalDiskConfig](rawConfig)
|
||||||
@@ -66,7 +66,7 @@ type S3Factory struct{}
|
|||||||
func NewS3Factory() S3Factory { return S3Factory{} }
|
func NewS3Factory() S3Factory { return S3Factory{} }
|
||||||
|
|
||||||
func (S3Factory) Type() storage.ProviderType { return storage.ProviderTypeS3 }
|
func (S3Factory) Type() storage.ProviderType { return storage.ProviderTypeS3 }
|
||||||
func (S3Factory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} }
|
func (S3Factory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} }
|
||||||
|
|
||||||
func (S3Factory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
func (S3Factory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
||||||
cfg, err := storage.DecodeConfig[storage.S3Config](rawConfig)
|
cfg, err := storage.DecodeConfig[storage.S3Config](rawConfig)
|
||||||
@@ -116,7 +116,7 @@ type WebDAVFactory struct{}
|
|||||||
func NewWebDAVFactory() WebDAVFactory { return WebDAVFactory{} }
|
func NewWebDAVFactory() WebDAVFactory { return WebDAVFactory{} }
|
||||||
|
|
||||||
func (WebDAVFactory) Type() storage.ProviderType { return storage.ProviderTypeWebDAV }
|
func (WebDAVFactory) Type() storage.ProviderType { return storage.ProviderTypeWebDAV }
|
||||||
func (WebDAVFactory) SensitiveFields() []string { return []string{"username", "password"} }
|
func (WebDAVFactory) SensitiveFields() []string { return []string{"username", "password"} }
|
||||||
|
|
||||||
func (WebDAVFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
func (WebDAVFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
||||||
cfg, err := storage.DecodeConfig[storage.WebDAVConfig](rawConfig)
|
cfg, err := storage.DecodeConfig[storage.WebDAVConfig](rawConfig)
|
||||||
@@ -187,7 +187,7 @@ type FTPFactory struct{}
|
|||||||
func NewFTPFactory() FTPFactory { return FTPFactory{} }
|
func NewFTPFactory() FTPFactory { return FTPFactory{} }
|
||||||
|
|
||||||
func (FTPFactory) Type() storage.ProviderType { return storage.ProviderTypeFTP }
|
func (FTPFactory) Type() storage.ProviderType { return storage.ProviderTypeFTP }
|
||||||
func (FTPFactory) SensitiveFields() []string { return []string{"username", "password"} }
|
func (FTPFactory) SensitiveFields() []string { return []string{"username", "password"} }
|
||||||
|
|
||||||
func (FTPFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
func (FTPFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
||||||
cfg, err := storage.DecodeConfig[storage.FTPConfig](rawConfig)
|
cfg, err := storage.DecodeConfig[storage.FTPConfig](rawConfig)
|
||||||
@@ -228,7 +228,7 @@ type AliyunOSSFactory struct{}
|
|||||||
func NewAliyunOSSFactory() AliyunOSSFactory { return AliyunOSSFactory{} }
|
func NewAliyunOSSFactory() AliyunOSSFactory { return AliyunOSSFactory{} }
|
||||||
|
|
||||||
func (AliyunOSSFactory) Type() storage.ProviderType { return storage.ProviderTypeAliyunOSS }
|
func (AliyunOSSFactory) Type() storage.ProviderType { return storage.ProviderTypeAliyunOSS }
|
||||||
func (AliyunOSSFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} }
|
func (AliyunOSSFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} }
|
||||||
|
|
||||||
// AliyunConfig 是阿里云 OSS 的用户配置。
|
// AliyunConfig 是阿里云 OSS 的用户配置。
|
||||||
type AliyunConfig struct {
|
type AliyunConfig struct {
|
||||||
@@ -269,7 +269,9 @@ type TencentCOSFactory struct{}
|
|||||||
func NewTencentCOSFactory() TencentCOSFactory { return TencentCOSFactory{} }
|
func NewTencentCOSFactory() TencentCOSFactory { return TencentCOSFactory{} }
|
||||||
|
|
||||||
func (TencentCOSFactory) Type() storage.ProviderType { return storage.ProviderTypeTencentCOS }
|
func (TencentCOSFactory) Type() storage.ProviderType { return storage.ProviderTypeTencentCOS }
|
||||||
func (TencentCOSFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} }
|
func (TencentCOSFactory) SensitiveFields() []string {
|
||||||
|
return []string{"accessKeyId", "secretAccessKey"}
|
||||||
|
}
|
||||||
|
|
||||||
// TencentConfig 是腾讯云 COS 的用户配置。
|
// TencentConfig 是腾讯云 COS 的用户配置。
|
||||||
type TencentConfig struct {
|
type TencentConfig struct {
|
||||||
@@ -305,7 +307,7 @@ type QiniuKodoFactory struct{}
|
|||||||
func NewQiniuKodoFactory() QiniuKodoFactory { return QiniuKodoFactory{} }
|
func NewQiniuKodoFactory() QiniuKodoFactory { return QiniuKodoFactory{} }
|
||||||
|
|
||||||
func (QiniuKodoFactory) Type() storage.ProviderType { return storage.ProviderTypeQiniuKodo }
|
func (QiniuKodoFactory) Type() storage.ProviderType { return storage.ProviderTypeQiniuKodo }
|
||||||
func (QiniuKodoFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} }
|
func (QiniuKodoFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} }
|
||||||
|
|
||||||
// QiniuConfig 是七牛云 Kodo 的用户配置。
|
// QiniuConfig 是七牛云 Kodo 的用户配置。
|
||||||
type QiniuConfig struct {
|
type QiniuConfig struct {
|
||||||
@@ -355,7 +357,9 @@ type RcloneFactory struct{}
|
|||||||
func NewRcloneFactory() RcloneFactory { return RcloneFactory{} }
|
func NewRcloneFactory() RcloneFactory { return RcloneFactory{} }
|
||||||
|
|
||||||
func (RcloneFactory) Type() storage.ProviderType { return storage.ProviderTypeRclone }
|
func (RcloneFactory) Type() storage.ProviderType { return storage.ProviderTypeRclone }
|
||||||
func (RcloneFactory) SensitiveFields() []string { return []string{"pass", "password", "secret_access_key", "client_secret", "token"} }
|
func (RcloneFactory) SensitiveFields() []string {
|
||||||
|
return []string{"pass", "password", "secret_access_key", "client_secret", "token"}
|
||||||
|
}
|
||||||
|
|
||||||
func (RcloneFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
func (RcloneFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
||||||
backend, _ := rawConfig["backend"].(string)
|
backend, _ := rawConfig["backend"].(string)
|
||||||
@@ -462,8 +466,10 @@ func NewBackendFactory(backendType string) GenericBackendFactory {
|
|||||||
return GenericBackendFactory{backendType: backendType, sensitive: sensitive}
|
return GenericBackendFactory{backendType: backendType, sensitive: sensitive}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f GenericBackendFactory) Type() storage.ProviderType { return storage.ProviderType(f.backendType) }
|
func (f GenericBackendFactory) Type() storage.ProviderType {
|
||||||
func (f GenericBackendFactory) SensitiveFields() []string { return f.sensitive }
|
return storage.ProviderType(f.backendType)
|
||||||
|
}
|
||||||
|
func (f GenericBackendFactory) SensitiveFields() []string { return f.sensitive }
|
||||||
|
|
||||||
func (f GenericBackendFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
func (f GenericBackendFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) {
|
||||||
root, _ := rawConfig["root"].(string)
|
root, _ := rawConfig["root"].(string)
|
||||||
|
|||||||
Reference in New Issue
Block a user