@@ -7,8 +7,10 @@ import (
7
7
"github.com/minio/minio-go/v7"
8
8
"github.com/minio/minio-go/v7/pkg/credentials"
9
9
"log"
10
+ "net/url"
10
11
"os"
11
12
"strconv"
13
+ "strings"
12
14
"time"
13
15
)
14
16
@@ -17,26 +19,55 @@ func main() {
17
19
log .Printf ("WARNING: Error loading .env file: %s\n " , err )
18
20
}
19
21
20
- postgresHost := flag .String ("postgres-host" , lookupEnvOrString ("POSTGRES_HOST" , "localhost" ), "connectionOptions host" )
21
- postgresPort := flag .Int ("postgres-port" , lookupEnvOrInt ("POSTGRES_PORT" , 5432 ), "connectionOptions port" )
22
- postgresUser := flag .String ("postgres-user" , lookupEnvOrString ("POSTGRES_USER" , "postgres" ), "connectionOptions user" )
23
- postgresPassword := flag .String ("postgres-password" , lookupEnvOrString ("POSTGRES_PASSWORD" , "postgres" ), "connectionOptions password" )
24
- postgresDB := flag .String ("postgres-db" , lookupEnvOrString ("POSTGRES_DB" , "postgres" ), "connectionOptions database" )
22
+ rawUrls := flag .String ("urls" , lookupEnvOrString ("URLS" , "" ), "comma separated list of urls to backup, these must be in the format postgres://<user>:<password>@<host>[:<port>]/<dbname>" )
25
23
26
24
s3Endpoint := flag .String ("s3-endpoint" , lookupEnvOrString ("S3_ENDPOINT" , "" ), "S3 endpoint" )
27
25
s3Bucket := flag .String ("s3-bucket" , lookupEnvOrString ("S3_BUCKET" , "postgres-backups" ), "S3 bucket" )
28
26
s3AccessKey := flag .String ("s3-access-key" , lookupEnvOrString ("S3_ACCESS_KEY" , "minio" ), "S3 access key" )
29
27
s3SecretKey := flag .String ("s3-secret-key" , lookupEnvOrString ("S3_SECRET_KEY" , "minioadmin" ), "S3 secret key" )
30
28
31
- every := flag .Duration ("every " , lookupEnvOrDuration ("EVERY " , 24 * time .Hour ), "How often to run the backup" )
29
+ interval := flag .Duration ("interval " , lookupEnvOrDuration ("INTERVAL " , 24 * time .Hour ), "How often to run the backup" )
32
30
33
31
flag .Parse ()
34
32
35
- must ("postgres-host " , postgresHost )
33
+ must ("urls " , rawUrls )
36
34
must ("s3-endpoint" , s3Endpoint )
37
35
must ("s3-access-key" , s3AccessKey )
38
36
must ("s3-secret-key" , s3SecretKey )
39
37
38
+ urls := make ([]connectionOptions , len (strings .Split (* rawUrls , "," )))
39
+ for i , rawUrl := range strings .Split (* rawUrls , "," ) {
40
+ parsedUrl , err := url .Parse (rawUrl )
41
+ if err != nil {
42
+ log .Fatalf ("Failed to parse url %s: %s" , rawUrl , err )
43
+ }
44
+
45
+ port := 5432
46
+ rawPort := parsedUrl .Port ()
47
+ if rawPort != "" {
48
+ port , err = strconv .Atoi (rawPort )
49
+ if err != nil {
50
+ log .Fatalf ("Failed to parse port %s: %s" , parsedUrl .Port (), err )
51
+ }
52
+ }
53
+
54
+ password , exist := parsedUrl .User .Password ()
55
+ if ! exist {
56
+ log .Fatalf ("Failed to parse password %s: %s" , parsedUrl .User , err )
57
+ }
58
+
59
+ urls [i ] = connectionOptions {
60
+ Host : parsedUrl .Hostname (),
61
+ Port : port ,
62
+ Database : strings .TrimPrefix (parsedUrl .Path , "/" ),
63
+ Username : parsedUrl .User .Username (),
64
+ Password : password ,
65
+ }
66
+ }
67
+ if len (urls ) == 0 {
68
+ log .Fatalf ("No URLs specified" )
69
+ }
70
+
40
71
s3 , err := minio .New (* s3Endpoint , & minio.Options {
41
72
Creds : credentials .NewStaticV4 (* s3AccessKey , * s3SecretKey , "" ),
42
73
Secure : true ,
@@ -46,36 +77,34 @@ func main() {
46
77
}
47
78
48
79
for {
49
- log .Printf ("Sleeping for %s" , * every )
50
- time .Sleep (* every )
51
-
52
- file := newFileName (* postgresDB )
53
- err = RunDump (& connectionOptions {
54
- Host : * postgresHost ,
55
- Port : * postgresPort ,
56
- Database : * postgresDB ,
57
- Username : * postgresUser ,
58
- Password : * postgresPassword ,
59
- }, file )
60
- if err != nil {
61
- log .Printf ("WARNING: Failed to dump database: %s" , err )
62
- continue
63
- }
80
+ for _ , u := range urls {
81
+ log .Printf ("Backing up %s" , u .Database )
64
82
65
- log . Printf ( "Uploading %s to %s" , file , * s3Bucket )
83
+ file := newFileName ( u . Database )
66
84
67
- if _ , err := s3 . FPutObject ( context . Background (), * s3Bucket , file , file , minio. PutObjectOptions {} ); err != nil {
68
- log .Printf ("WARNING: Failed to upload %s to %s : %s" , file , * s3Bucket , err )
69
- continue
70
- }
85
+ if err = RunDump ( & u , file ); err != nil {
86
+ log .Printf ("WARNING: Failed to dump database : %s" , err )
87
+ continue
88
+ }
71
89
72
- log .Printf ("Removing %s" , file )
73
- if err := os .Remove (file ); err != nil {
74
- log .Printf ("WARNING: Failed to remove %s: %s" , file , err )
75
- continue
90
+ log .Printf ("Uploading %s to %s" , file , * s3Bucket )
91
+
92
+ if _ , err := s3 .FPutObject (context .Background (), * s3Bucket , file , file , minio.PutObjectOptions {}); err != nil {
93
+ log .Printf ("WARNING: Failed to upload %s to %s: %s" , file , * s3Bucket , err )
94
+ continue
95
+ }
96
+
97
+ log .Printf ("Removing %s" , file )
98
+ if err := os .Remove (file ); err != nil {
99
+ log .Printf ("WARNING: Failed to remove %s: %s" , file , err )
100
+ continue
101
+ }
102
+
103
+ log .Printf ("Done" )
76
104
}
77
105
78
- log .Printf ("Done" )
106
+ log .Printf ("Sleeping for %s" , * interval )
107
+ time .Sleep (* interval )
79
108
}
80
109
}
81
110
@@ -87,19 +116,6 @@ func lookupEnvOrString(key string, defaultVal string) string {
87
116
return defaultVal
88
117
}
89
118
90
- func lookupEnvOrInt (key string , defaultVal int ) int {
91
- if val , ok := os .LookupEnv (key ); ok {
92
- parsed , err := strconv .Atoi (val )
93
- if err != nil {
94
- log .Fatal (err )
95
- }
96
-
97
- return parsed
98
- }
99
-
100
- return defaultVal
101
- }
102
-
103
119
func lookupEnvOrDuration (key string , defaultVal time.Duration ) time.Duration {
104
120
if val , ok := os .LookupEnv (key ); ok {
105
121
parsed , err := time .ParseDuration (val )
0 commit comments