Skip to content

Commit

Permalink
feat: 数据备份前端
Browse files Browse the repository at this point in the history
  • Loading branch information
devhaozi committed Oct 13, 2024
1 parent e1bcabe commit f235492
Show file tree
Hide file tree
Showing 30 changed files with 557 additions and 71 deletions.
21 changes: 16 additions & 5 deletions internal/biz/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@ package biz

import "github.com/TheTNB/panel/pkg/types"

type BackupType string

const (
BackupTypePath BackupType = "path"
BackupTypeWebsite BackupType = "website"
BackupTypeMySQL BackupType = "mysql"
BackupTypePostgres BackupType = "postgres"
BackupTypeRedis BackupType = "redis"
BackupTypePanel BackupType = "panel"
)

type BackupRepo interface {
List(typ string) ([]*types.BackupFile, error)
Create(typ, target string, path ...string) error
Delete(typ, name string) error
Restore(typ, backup, target string) error
List(typ BackupType) ([]*types.BackupFile, error)
Create(typ BackupType, target string, path ...string) error
Delete(typ BackupType, name string) error
Restore(typ BackupType, backup, target string) error
ClearExpired(path, prefix string, save int) error
CutoffLog(path, target string) error
GetPath(typ string) (string, error)
GetPath(typ BackupType) (string, error)
}
59 changes: 40 additions & 19 deletions internal/data/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,38 @@ func NewBackupRepo() biz.BackupRepo {
}

// List 备份列表
func (r *backupRepo) List(typ string) ([]*types.BackupFile, error) {
backupPath, err := r.GetPath(typ)
func (r *backupRepo) List(typ biz.BackupType) ([]*types.BackupFile, error) {
path, err := r.GetPath(typ)
if err != nil {
return nil, err
}

files, err := io.ReadDir(backupPath)
files, err := io.ReadDir(path)
if err != nil {
return nil, err
}

var backupList []*types.BackupFile
list := make([]*types.BackupFile, 0)
for _, file := range files {
info, err := file.Info()
if err != nil {
continue
}
backupList = append(backupList, &types.BackupFile{
list = append(list, &types.BackupFile{
Name: file.Name(),
Path: filepath.Join(path, file.Name()),
Size: str.FormatBytes(float64(info.Size())),
})
}

return backupList, nil
return list, nil
}

// Create 创建备份
// typ 备份类型
// target 目标名称
// path 可选备份保存路径
func (r *backupRepo) Create(typ, target string, path ...string) error {
func (r *backupRepo) Create(typ biz.BackupType, target string, path ...string) error {
defPath, err := r.GetPath(typ)
if err != nil {
return err
Expand All @@ -74,13 +75,13 @@ func (r *backupRepo) Create(typ, target string, path ...string) error {
}

switch typ {
case "website":
case biz.BackupTypeWebsite:
return r.createWebsite(defPath, target)
case "mysql":
case biz.BackupTypeMySQL:
return r.createMySQL(defPath, target)
case "postgres":
case biz.BackupTypePostgres:
return r.createPostgres(defPath, target)
case "panel":
case biz.BackupTypePanel:
return r.createPanel(defPath)

}
Expand All @@ -89,7 +90,7 @@ func (r *backupRepo) Create(typ, target string, path ...string) error {
}

// Delete 删除备份
func (r *backupRepo) Delete(typ, name string) error {
func (r *backupRepo) Delete(typ biz.BackupType, name string) error {
path, err := r.GetPath(typ)
if err != nil {
return err
Expand All @@ -103,7 +104,7 @@ func (r *backupRepo) Delete(typ, name string) error {
// typ 备份类型
// backup 备份压缩包,可以是绝对路径或者相对路径
// target 目标名称
func (r *backupRepo) Restore(typ, backup, target string) error {
func (r *backupRepo) Restore(typ biz.BackupType, backup, target string) error {
if !io.Exists(backup) {
path, err := r.GetPath(typ)
if err != nil {
Expand All @@ -113,11 +114,11 @@ func (r *backupRepo) Restore(typ, backup, target string) error {
}

switch typ {
case "website":
case biz.BackupTypeWebsite:
return r.restoreWebsite(backup, target)
case "mysql":
case biz.BackupTypeMySQL:
return r.restoreMySQL(backup, target)
case "postgres":
case biz.BackupTypePostgres:
return r.restorePostgres(backup, target)
}

Expand Down Expand Up @@ -189,13 +190,16 @@ func (r *backupRepo) ClearExpired(path, prefix string, save int) error {
}

// GetPath 获取备份路径
func (r *backupRepo) GetPath(typ string) (string, error) {
func (r *backupRepo) GetPath(typ biz.BackupType) (string, error) {
backupPath, err := r.setting.Get(biz.SettingKeyBackupPath)
if err != nil {
return "", err
}
if !slices.Contains([]biz.BackupType{biz.BackupTypePath, biz.BackupTypeWebsite, biz.BackupTypeMySQL, biz.BackupTypePostgres, biz.BackupTypeRedis, biz.BackupTypePanel}, typ) {
return "", errors.New("未知备份类型")
}

backupPath = filepath.Join(backupPath, typ)
backupPath = filepath.Join(backupPath, string(typ))
if !io.Exists(backupPath) {
if err = io.Mkdir(backupPath, 0644); err != nil {
return "", err
Expand All @@ -216,11 +220,22 @@ func (r *backupRepo) createWebsite(to string, name string) error {
return err
}

var paths []string
dirs, err := io.ReadDir(website.Path)
if err != nil {
return err
}
for _, item := range dirs {
paths = append(paths, filepath.Join(website.Path, item.Name()))
}

start := time.Now()
backup := filepath.Join(to, fmt.Sprintf("%s_%s.zip", website.Name, time.Now().Format("20060102150405")))
if _, err = shell.Execf(`cd '%s' && zip -r '%s' .`, website.Path, backup); err != nil {
if err = io.Compress(paths, backup, io.Zip); err != nil {
return err
}

color.Greenln(fmt.Sprintf("|-备份耗时:%s", time.Since(start).String()))
color.Greenln(fmt.Sprintf("|-已备份至文件:%s", backup))
return nil
}
Expand Down Expand Up @@ -249,6 +264,7 @@ func (r *backupRepo) createMySQL(to string, name string) error {
if err = os.Setenv("MYSQL_PWD", rootPassword); err != nil {
return err
}
start := time.Now()
backup := filepath.Join(to, fmt.Sprintf("%s_%s.sql", name, time.Now().Format("20060102150405")))
if _, err = shell.Execf(`mysqldump -u root '%s' > '%s'`, name, backup); err != nil {
return err
Expand All @@ -264,6 +280,7 @@ func (r *backupRepo) createMySQL(to string, name string) error {
return err
}

color.Greenln(fmt.Sprintf("|-备份耗时:%s", time.Since(start).String()))
color.Greenln(fmt.Sprintf("|-已备份至文件:%s", backup+".zip"))
return nil
}
Expand All @@ -285,6 +302,7 @@ func (r *backupRepo) createPostgres(to string, name string) error {
return err
}

start := time.Now()
backup := filepath.Join(to, fmt.Sprintf("%s_%s.sql", name, time.Now().Format("20060102150405")))
if _, err = shell.Execf(`su - postgres -c "pg_dump '%s'" > '%s'`, name, backup); err != nil {
return err
Expand All @@ -297,6 +315,7 @@ func (r *backupRepo) createPostgres(to string, name string) error {
return err
}

color.Greenln(fmt.Sprintf("|-备份耗时:%s", time.Since(start).String()))
color.Greenln(fmt.Sprintf("|-已备份至文件:%s", backup+".zip"))
return nil
}
Expand All @@ -309,6 +328,7 @@ func (r *backupRepo) createPanel(to string) error {
return err
}

start := time.Now()
if err := io.Compress([]string{
filepath.Join(app.Root, "panel"),
"/usr/local/sbin/panel-cli",
Expand All @@ -317,6 +337,7 @@ func (r *backupRepo) createPanel(to string) error {
return err
}

color.Greenln(fmt.Sprintf("|-备份耗时:%s", time.Since(start).String()))
color.Greenln(fmt.Sprintf("|-已备份至文件:%s", backup))
return nil
}
Expand Down
22 changes: 22 additions & 0 deletions internal/http/request/backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package request

type BackupList struct {
Type string `json:"type" form:"type" validate:"required,oneof=path website mysql postgres redis panel"`
}

type BackupCreate struct {
Type string `json:"type" form:"type" validate:"required,oneof=website mysql postgres redis panel"`
Target string `json:"target" form:"target" validate:"required"`
Path string `json:"path" form:"path"`
}

type BackupFile struct {
Type string `json:"type" form:"type" validate:"required,oneof=website mysql postgres redis panel"`
File string `json:"file" form:"file" validate:"required"`
}

type BackupRestore struct {
Type string `json:"type" form:"type" validate:"required,oneof=website mysql postgres redis panel"`
File string `json:"file" form:"file" validate:"required"`
Target string `json:"target" form:"target" validate:"required"`
}
5 changes: 0 additions & 5 deletions internal/http/request/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ type FileSave struct {
Content string `form:"content" json:"content"`
}

type FileUpload struct {
Path string `json:"path" form:"path"`
File []byte `json:"file" form:"file"`
}

type FileMove struct {
Source string `form:"source" json:"source"`
Target string `form:"target" json:"target"`
Expand Down
2 changes: 1 addition & 1 deletion internal/job/panel_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (receiver *PanelTask) Run() {
}

// 备份面板
if err := receiver.backupRepo.Create("panel", ""); err != nil {
if err := receiver.backupRepo.Create(biz.BackupTypePanel, ""); err != nil {
app.Logger.Error("备份面板失败", zap.Error(err))
}

Expand Down
12 changes: 5 additions & 7 deletions internal/route/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,14 @@ func Http(r chi.Router) {
r.Post("/{id}/status", website.UpdateStatus)
})

// TODO
r.Route("/backup", func(r chi.Router) {
r.Use(middleware.MustLogin)
backup := service.NewBackupService()
r.Get("/backup", backup.List)
r.Post("/create", backup.Create)
r.Post("/update", backup.Update)
r.Get("/{id}", backup.Get)
r.Delete("/{id}", backup.Delete)
r.Delete("/{id}/restore", backup.Restore)
r.Get("/{type}", backup.List)
r.Post("/{type}", backup.Create)
r.Post("/{type}/upload", backup.Upload)
r.Delete("/{type}/delete", backup.Delete)
r.Post("/{type}/restore", backup.Restore)
})

r.Route("/cert", func(r chi.Router) {
Expand Down
Loading

0 comments on commit f235492

Please sign in to comment.