@@ -7,8 +7,10 @@ import (
77 "github.com/minio/minio-go/v7"
88 "github.com/minio/minio-go/v7/pkg/credentials"
99 "log"
10+ "net/url"
1011 "os"
1112 "strconv"
13+ "strings"
1214 "time"
1315)
1416
@@ -17,26 +19,55 @@ func main() {
1719 log .Printf ("WARNING: Error loading .env file: %s\n " , err )
1820 }
1921
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>" )
2523
2624 s3Endpoint := flag .String ("s3-endpoint" , lookupEnvOrString ("S3_ENDPOINT" , "" ), "S3 endpoint" )
2725 s3Bucket := flag .String ("s3-bucket" , lookupEnvOrString ("S3_BUCKET" , "postgres-backups" ), "S3 bucket" )
2826 s3AccessKey := flag .String ("s3-access-key" , lookupEnvOrString ("S3_ACCESS_KEY" , "minio" ), "S3 access key" )
2927 s3SecretKey := flag .String ("s3-secret-key" , lookupEnvOrString ("S3_SECRET_KEY" , "minioadmin" ), "S3 secret key" )
3028
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" )
3230
3331 flag .Parse ()
3432
35- must ("postgres-host " , postgresHost )
33+ must ("urls " , rawUrls )
3634 must ("s3-endpoint" , s3Endpoint )
3735 must ("s3-access-key" , s3AccessKey )
3836 must ("s3-secret-key" , s3SecretKey )
3937
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+
4071 s3 , err := minio .New (* s3Endpoint , & minio.Options {
4172 Creds : credentials .NewStaticV4 (* s3AccessKey , * s3SecretKey , "" ),
4273 Secure : true ,
@@ -46,36 +77,34 @@ func main() {
4677 }
4778
4879 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 )
6482
65- log . Printf ( "Uploading %s to %s" , file , * s3Bucket )
83+ file := newFileName ( u . Database )
6684
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+ }
7189
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" )
76104 }
77105
78- log .Printf ("Done" )
106+ log .Printf ("Sleeping for %s" , * interval )
107+ time .Sleep (* interval )
79108 }
80109}
81110
@@ -87,19 +116,6 @@ func lookupEnvOrString(key string, defaultVal string) string {
87116 return defaultVal
88117}
89118
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-
103119func lookupEnvOrDuration (key string , defaultVal time.Duration ) time.Duration {
104120 if val , ok := os .LookupEnv (key ); ok {
105121 parsed , err := time .ParseDuration (val )
0 commit comments