Add restore, backup, list, and clean commands
parent
6b5ad0743a
commit
fbb36bc94a
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue