109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"local/args"
|
|
"local/storage"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"path/filepath"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
type Config struct {
|
|
n int
|
|
conf string
|
|
rclone string
|
|
ns string
|
|
root string
|
|
store string
|
|
}
|
|
|
|
func main() {
|
|
conf := config()
|
|
log.Println(conf)
|
|
store, err := storage.New(storage.TypeFromString(conf.store), conf.conf, path.Join(conf.rclone+":", conf.ns))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err := push(conf.root, store); err != nil {
|
|
panic(err)
|
|
}
|
|
if err := clean(conf.n, store); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func config() Config {
|
|
as := args.NewArgSet()
|
|
as.Append(args.INT, "n", "number of backups to retain", 5)
|
|
as.Append(args.STRING, "conf", "path to rclone conf", path.Join(os.Getenv("HOME"), "/.config/rclone/rclone.conf"))
|
|
as.Append(args.STRING, "root", "path to root", "./public")
|
|
as.Append(args.STRING, "ns", "ns for backups", path.Join("lastn", "dev"))
|
|
as.Append(args.STRING, "rclone", "rclone backend name", "blapointe-drive-enc")
|
|
as.Append(args.STRING, "store", "type of store, like [map rclone]", "map")
|
|
if err := as.Parse(); err != nil {
|
|
panic(err)
|
|
}
|
|
return Config{
|
|
n: as.Get("n").GetInt(),
|
|
conf: as.Get("conf").GetString(),
|
|
rclone: as.Get("rclone").GetString(),
|
|
root: as.Get("root").GetString(),
|
|
ns: as.Get("ns").GetString(),
|
|
store: as.Get("store").GetString(),
|
|
}
|
|
}
|
|
|
|
func push(root string, store storage.DB) error {
|
|
root, err := filepath.Abs(root)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
archive := path.Join(
|
|
os.TempDir(),
|
|
fmt.Sprintf(
|
|
"%s.tar",
|
|
time.Now().Format("2006.01.02.15.04.05"),
|
|
),
|
|
)
|
|
cmd := exec.Command(
|
|
"tar",
|
|
"-C",
|
|
path.Dir(root),
|
|
"-czf",
|
|
archive,
|
|
root,
|
|
)
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("%v: %s", err, out)
|
|
}
|
|
b, err := ioutil.ReadFile(archive)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Println("Created backup", path.Base(archive))
|
|
return store.Set(path.Base(archive), b)
|
|
}
|
|
|
|
func clean(n int, store storage.DB) error {
|
|
backups, err := store.List(nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sort.Strings(backups)
|
|
for i := 0; i < len(backups)-n; i++ {
|
|
log.Println("Pruning old backup", backups[i])
|
|
err := store.Set(backups[i], nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|