-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackup_agent.go
117 lines (92 loc) · 2.87 KB
/
backup_agent.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
)
func main() {
port := "9191"
envPort := os.Getenv("BACKUP_AGENT_PORT")
envBackupCommand := os.Getenv("BACKUP_AGENT_BACKUP_SCRIPT")
envRestoreCommand := os.Getenv("BACKUP_AGENT_RESTORE_SCRIPT")
if envPort != "" {
port = envPort
}
intPort, errPort := strconv.Atoi(port)
if errPort != nil {
panic("Port must be a number")
}
portPtr := flag.Int("port", intPort, "port to start server on, default 9191. Also can be specified by BACKUP_AGENT_PORT environment variable")
backupCmdPtr := flag.String("backup", envBackupCommand, "backup command to run. Also can be specified by BACKUP_AGENT_BACKUP_SCRIPT environment variable")
restoreCmdPtr := flag.String("restore", envRestoreCommand, "restore command to run. Also can be specified by BACKUP_AGENT_RESTORE_SCRIPT environment variable")
flag.Parse()
port = strconv.Itoa(*portPtr)
fmt.Println("Backup command:" + *backupCmdPtr)
fmt.Println("Restore command:" + *restoreCmdPtr)
http.HandleFunc("/backup", func(w http.ResponseWriter, r *http.Request) {
var stdout, stderr bytes.Buffer
cmd := exec.Command("/bin/sh", "-c", *backupCmdPtr)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
fileName := strings.TrimSpace(outStr)
_, fileErr := os.Stat(fileName)
if err != nil || fileErr != nil {
outError := outStr + "\n" + errStr
if err != nil {
outError += err.Error()
}
if fileErr != nil {
outError += fileErr.Error()
}
http.Error(w, outError, http.StatusInternalServerError)
} else {
log.Println("Sending backup file: ", fileName)
http.ServeFile(w, r, fileName)
}
})
http.HandleFunc("/restore", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, *restoreCmdPtr)
tmpfile, err := ioutil.TempFile("", "")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
panic(err)
}
defer os.Remove(tmpfile.Name())
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
panic(err)
}
if _, err := tmpfile.Write(body); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
panic(err)
}
if err := tmpfile.Close(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
panic(err)
}
cmd := exec.Command("/bin/sh", "-c", *restoreCmdPtr+" "+tmpfile.Name())
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
outError := string(stdoutStderr) + err.Error()
http.Error(w, outError, http.StatusInternalServerError)
} else {
log.Println("Backup restored")
fmt.Fprintf(w, string(stdoutStderr))
}
})
fmt.Println("Starting backup server on port " + port)
err := http.ListenAndServe(":"+port, nil)
if err != nil {
panic(err)
}
}