Add restore, backup, list, and clean commands

master
bel 2020-02-01 22:24:08 +00:00
parent 6b5ad0743a
commit fbb36bc94a
2 changed files with 98 additions and 11 deletions

0
README.md Normal file → Executable file
View File

107
main.go Normal file → Executable file
View File

@ -1,7 +1,9 @@
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"local/args"
"local/storage"
@ -21,20 +23,42 @@ type Config struct {
ns string
root string
store string
cmd string
}
type LastN struct {
store storage.DB
conf Config
}
func main() {
conf := config()
log.Println(conf)
store, err := storage.New(storage.TypeFromString(conf.store), conf.conf, path.Join(conf.rclone+":", conf.ns))
storage, 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 {
lastn := &LastN{
conf: conf,
store: storage,
}
actions := []func() error{}
switch conf.cmd {
case "backup":
actions = append(actions, lastn.push, lastn.clean)
case "list":
actions = append(actions, lastn.list)
case "clean":
actions = append(actions, lastn.clean)
case "restore":
actions = append(actions, lastn.restore)
default:
panic(fmt.Sprintf("not impl: %s"))
}
for _, action := range actions {
if err := action(); err != nil {
panic(err)
}
if err := clean(conf.n, store); err != nil {
panic(err)
}
}
@ -46,20 +70,28 @@ func config() Config {
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")
as.Append(args.STRING, "cmd", "[backup, restore, list, clean]", "backup")
if err := as.Parse(); err != nil {
panic(err)
}
root, err := filepath.Abs(as.Get("root").GetString())
if 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(),
root: root,
ns: as.Get("ns").GetString(),
store: as.Get("store").GetString(),
cmd: as.Get("cmd").GetString(),
}
}
func push(root string, store storage.DB) error {
func (lastN *LastN) push() error {
root := lastN.conf.root
store := lastN.store
root, err := filepath.Abs(root)
if err != nil {
return err
@ -73,11 +105,11 @@ func push(root string, store storage.DB) error {
)
cmd := exec.Command(
"tar",
"-C",
path.Dir(root),
"-czf",
archive,
root,
"-C",
path.Dir(root),
path.Base(root),
)
out, err := cmd.CombinedOutput()
if err != nil {
@ -91,7 +123,9 @@ func push(root string, store storage.DB) error {
return store.Set(path.Base(archive), b)
}
func clean(n int, store storage.DB) error {
func (lastN *LastN) clean() error {
n := lastN.conf.n
store := lastN.store
backups, err := store.List(nil)
if err != nil {
return err
@ -106,3 +140,56 @@ func clean(n int, store storage.DB) error {
}
return nil
}
func (lastN *LastN) list() error {
store := lastN.store
backups, err := store.List(nil)
if err != nil {
return err
}
sort.Strings(backups)
for _, backup := range backups {
log.Println(backup)
}
return nil
}
func (lastN *LastN) restore() error {
root := lastN.conf.root + "-restore"
os.RemoveAll(root)
if err := os.MkdirAll(root, os.ModePerm); err != nil {
return err
}
store := lastN.store
backups, err := store.List(nil)
if err != nil {
return fmt.Errorf("cannot list: %v", err)
}
sort.Strings(backups)
backup := backups[len(backups)-1]
b, err := store.Get(backup)
if err != nil {
return fmt.Errorf("cannot get %s: %v", backup, err)
}
log.Printf("restoring %s (%v) in %s", backup, len(b), root)
cmd := exec.Command(
"tar",
"-C",
root,
"-xzf",
"-",
)
stdin, err := cmd.StdinPipe()
if err != nil {
return fmt.Errorf("cannot get stdin: %v", err)
}
go func() {
defer stdin.Close()
io.Copy(stdin, bytes.NewReader(b))
}()
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed tar -xf: %v: %s", err, out)
}
return nil
}