Files
eiblog/cmd/backup/handler/timer/qiniu/qiniu.go
2025-07-16 19:45:50 +08:00

139 lines
3.1 KiB
Go

package qiniu
import (
"context"
"errors"
"fmt"
"net/url"
"os"
"os/exec"
"path/filepath"
"time"
"github.com/eiblog/eiblog/cmd/backup/config"
"github.com/eiblog/eiblog/cmd/backup/handler/internal"
"github.com/eiblog/eiblog/pkg/connector/db"
"github.com/eiblog/eiblog/pkg/third/qiniu"
)
// BackupRestorer qiniu backup restorer
type BackupRestorer struct{}
// Backup implements timer.BackupRestorer
func (s BackupRestorer) Backup(now time.Time) error {
switch config.Conf.Database.Driver {
case "mongodb":
return backupFromMongoDB(now)
default:
return errors.New("unsupported source backup to qiniu: " +
config.Conf.Database.Driver)
}
}
// Restore implements timer.BackupRestorer
func (s BackupRestorer) Restore() error {
switch config.Conf.Database.Driver {
case "mongodb":
return restoreToMongoDB()
default:
return errors.New("unsupported source restore from qiniu: " +
config.Conf.Database.Driver)
}
}
func backupFromMongoDB(now time.Time) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*20)
defer cancel()
// dump
u, err := url.Parse(config.Conf.Database.Source)
if err != nil {
return err
}
arg := fmt.Sprintf("mongodump -h %s -d eiblog -o /tmp", u.Host)
cmd := exec.CommandContext(ctx, "sh", "-c", arg)
err = cmd.Run()
if err != nil {
return err
}
// tar
name := fmt.Sprintf("eiblog-%s.tar.gz", now.Format("2006-01-02"))
arg = fmt.Sprintf("tar czf /tmp/%s -C /tmp eiblog", name)
cmd = exec.CommandContext(ctx, "sh", "-c", arg)
err = cmd.Run()
if err != nil {
return err
}
// upload file
f, err := os.Open("/tmp/" + name)
if err != nil {
return err
}
s, err := f.Stat()
if err != nil {
return err
}
uploadParams := qiniu.UploadParams{
Name: filepath.Join("blog", name), // blog/eiblog-xx.tar.gz
Size: s.Size(),
Data: f,
NoCompletePath: true,
}
_, err = internal.QiniuClient.Upload(uploadParams)
if err != nil {
return err
}
// after days delete
deleteParams := qiniu.DeleteParams{
Name: filepath.Join("blog", name), // blog/eiblog-xx.tar.gz
Days: config.Conf.Validity,
NoCompletePath: true,
}
return internal.QiniuClient.Delete(deleteParams)
}
func restoreToMongoDB() error {
// backup file
params := qiniu.ContentParams{
Prefix: "blog/",
}
raw, err := internal.QiniuClient.Content(params)
if err != nil {
return err
}
f, err := os.OpenFile("/tmp/eiblog.tar.gz", os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return err
}
_, _ = f.Write(raw)
defer f.Close()
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*20)
defer cancel()
// drop database
mdb, err := db.NewMDB(config.Conf.Database)
if err != nil {
return err
}
err = mdb.Drop(ctx)
if err != nil {
return err
}
// unarchive
arg := "tar xzf /tmp/eiblog.tar.gz -C /tmp"
cmd := exec.CommandContext(ctx, "sh", "-c", arg)
err = cmd.Run()
if err != nil {
return err
}
// restore
u, err := url.Parse(config.Conf.Database.Source)
if err != nil {
return err
}
arg = fmt.Sprintf("mongorestore -h %s -d eiblog /tmp/eiblog", u.Host)
cmd = exec.CommandContext(ctx, "sh", "-c", arg)
return cmd.Run()
}