Skip to content

Commit 889dcf8

Browse files
authored
Rewrite on golang.
1 parent bdd6af4 commit 889dcf8

File tree

4 files changed

+158
-1
lines changed

4 files changed

+158
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
pgsql-dumper-linux-x86_64
1+
/bin
2+
*.pgpass

compile.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
3+
echo "Compiling for Windows amd64..."
4+
GOOS=windows GOARCH=amd64 go build -o bin/psql-dumper-x86_64.exe main.go
5+
6+
echo "Compiling for Windows i386..."
7+
GOOS=windows GOARCH=386 go build -o bin/psql-dumper-i386.exe main.go
8+
9+
echo "Compiling for Darwin amd64..."
10+
GOOS=darwin GOARCH=amd64 go build -o bin/psql-dumper-x86_64-darwin main.go
11+
12+
echo "Compiling for Linux amd64..."
13+
GOOS=linux GOARCH=amd64 go build -o bin/psql-dumper-x86_64-linux main.go
14+
15+
echo "Compiling for Linux i386..."
16+
GOOS=linux GOARCH=386 go build -o bin/psql-dumper-i386-linux main.go
17+
18+
echo "Done!!"

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module hugebot/psql-dumper
2+
3+
go 1.18

main.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"encoding/base64"
6+
"encoding/json"
7+
"flag"
8+
"fmt"
9+
"log"
10+
"net/http"
11+
"os"
12+
"os/exec"
13+
"os/user"
14+
"time"
15+
)
16+
17+
var (
18+
useHelp bool
19+
20+
actor string
21+
repo string
22+
token string
23+
dbName string
24+
)
25+
26+
const (
27+
apiUrl = "https://api.github.com"
28+
)
29+
30+
type PutRequest struct {
31+
Message string `json:"message"`
32+
Content string `json:"content"`
33+
}
34+
35+
func main() {
36+
37+
date := time.Now()
38+
formattedDate := date.Format(time.RFC3339)
39+
40+
info, err := user.Current()
41+
if err != nil {
42+
log.Fatal(err)
43+
}
44+
45+
if info.Username != "postgres" {
46+
log.Fatal("This command needs to be launched by 'postgres' user.")
47+
}
48+
49+
flag.BoolVar(&useHelp, "help", false, "Show this help menu.")
50+
flag.StringVar(&actor, "actor", "", "The GitHub repository actor.")
51+
flag.StringVar(&repo, "repo", "", "The GitHub repository name.")
52+
flag.StringVar(&token, "token", "", "The GitHub Personal Access Token.")
53+
flag.StringVar(&dbName, "db", "", "The name of the database to backup.")
54+
55+
flag.Parse()
56+
57+
if useHelp {
58+
flag.PrintDefaults()
59+
os.Exit(0)
60+
}
61+
62+
if len(actor) < 1 {
63+
log.Fatal("Actor cannot be empty, use --help.")
64+
}
65+
66+
if len(repo) < 1 {
67+
log.Fatal("Repo cannot be empty, use --help.")
68+
}
69+
70+
if len(token) < 1 {
71+
log.Fatal("Token cannot be empty, use --help.")
72+
}
73+
74+
if len(dbName) < 1 {
75+
log.Fatal("Database Name cannot be empty, use --help.")
76+
}
77+
78+
log.Printf("Creating backup from database '%s'...\n", dbName)
79+
80+
tempDir := os.TempDir()
81+
fileName := fmt.Sprintf("dump-%s-%s.backup", dbName, formattedDate)
82+
destination := fmt.Sprintf("%s/%s", tempDir, fileName)
83+
84+
cmd := exec.Command("pg_dump", "-Z5", "-Fc", dbName, "-f", destination)
85+
86+
cmd.Stdout = os.Stdout
87+
cmd.Stderr = os.Stderr
88+
89+
if err := cmd.Run(); err != nil {
90+
log.Fatal(err)
91+
}
92+
93+
log.Printf("Backup created successfully on %s.\n", destination)
94+
log.Printf("Encoding file to Base64...\n")
95+
96+
content, err := os.ReadFile(destination)
97+
if err != nil {
98+
log.Fatal(err)
99+
}
100+
101+
encodedFile := base64.StdEncoding.EncodeToString(content)
102+
103+
log.Printf("Uploading encoded backup to GitHub Repository %s/%s...\n", actor, repo)
104+
105+
body := PutRequest{
106+
Message: fmt.Sprintf("Upload backup from %s at %s", dbName, formattedDate),
107+
Content: encodedFile,
108+
}
109+
110+
var buf bytes.Buffer
111+
if err := json.NewEncoder(&buf).Encode(body); err != nil {
112+
log.Fatal(err)
113+
}
114+
115+
req, err := http.NewRequest("PUT", fmt.Sprintf("%s/repos/%s/%s/contents/%s", apiUrl, actor, repo, fileName), &buf)
116+
if err != nil {
117+
log.Fatal(err)
118+
}
119+
120+
req.Header.Add("Authorization", fmt.Sprintf("token %s", token))
121+
122+
resp, err := http.DefaultClient.Do(req)
123+
if err != nil {
124+
log.Fatal(err)
125+
}
126+
127+
defer resp.Body.Close()
128+
129+
if resp.StatusCode != 201 {
130+
log.Fatal(resp.Status)
131+
}
132+
133+
log.Printf("Successfully uploaded encoded backup to GitHub.\n\n")
134+
135+
}

0 commit comments

Comments
 (0)