11package main
22
33import (
4+ "fmt"
5+ "io"
46 syslog "log"
57 "os"
8+ "time"
69
10+ "github.com/aweris/postgres-data-dump/database"
11+ "github.com/aweris/postgres-data-dump/dump"
12+ "github.com/aweris/postgres-data-dump/internal/helpers"
713 "github.com/aweris/postgres-data-dump/internal/log"
14+ "github.com/aweris/postgres-data-dump/storage"
15+ "github.com/aweris/postgres-data-dump/storage/backend"
16+ "github.com/aweris/postgres-data-dump/storage/backend/fs"
817 "github.com/spf13/pflag"
918)
1019
@@ -23,6 +32,15 @@ func main() {
2332 logFormat string
2433 verbose bool
2534
35+ // database
36+ dbc = database.Config {}
37+
38+ // dump
39+ dc = dump.Config {}
40+
41+ // backend
42+ bc = backend.Config {}
43+
2644 // other
2745 showVersion bool
2846 )
@@ -37,13 +55,49 @@ func main() {
3755 flag .StringVar (& logFormat , "log-format" , log .FormatFmt , "log format to use. ('fmt', 'json')" )
3856 flag .BoolVarP (& verbose , "verbose" , "v" , false , "verbose output" )
3957
58+ // database flags
59+ flag .StringVar (& dbc .Addr , "addr" , database .DefaultAddr , "TCP host:port or Unix socket depending on Network" )
60+ flag .StringVar (& dbc .Database , "database" , database .DefaultDatabase , "Database name" )
61+ flag .StringVar (& dbc .User , "user" , database .DefaultUser , "Database user" )
62+ flag .StringVar (& dbc .Password , "pass" , database .DefaultPassword , "Database password" )
63+ flag .DurationVar (& dbc .DialTimeout , "dial-timeout" , database .DefaultDialTimeout , "Dial timeout for establishing new connections" )
64+ flag .DurationVar (& dbc .ReadTimeout , "read-timeout" , database .DefaultReadTimeout , "Timeout for socket reads. If reached, commands will fail" )
65+ flag .IntVar (& dbc .MaxRetries , "max-retry" , database .DefaultMaxRetries , "Maximum number of retries before giving up." )
66+
67+ // dump flags
68+ flag .StringVar (& dc .ManifestFile , "manifest-file" , dump .DefaultManifestFile , "Path to manifest file" )
69+
70+ // backend
71+ flag .StringVar (& bc .Type , "backend" , backend .FileSystem , "storage backend to use (filesystem)" )
72+
73+ // backend filesystem
74+ flag .StringVar (& bc .FileSystem .Root , "filesystem-root" , fs .DefaultRoot , "local filesystem root directory" )
75+
4076 // other flags
4177 flag .BoolVar (& showVersion , "version" , false , "Prints version info" )
4278
4379 // bind environment variables
4480 bindEnv (flag .Lookup ("log-level" ), "PDD_LOG_LEVEL" )
4581 bindEnv (flag .Lookup ("log-format" ), "PDD_LOG_FORMAT" )
4682
83+ // database variables
84+ bindEnv (flag .Lookup ("addr" ), "PDD_ADDR" )
85+ bindEnv (flag .Lookup ("database" ), "PDD_DATABASE" )
86+ bindEnv (flag .Lookup ("user" ), "PDD_USER" )
87+ bindEnv (flag .Lookup ("pass" ), "PDD_PASS" )
88+ bindEnv (flag .Lookup ("dial-timeout" ), "PDD_DIAL_TIMEOUT" )
89+ bindEnv (flag .Lookup ("read-timeout" ), "PDD_READ_TIMEOUT" )
90+ bindEnv (flag .Lookup ("max-retry" ), "PDD_MAX_RETRY" )
91+
92+ // dump variables
93+ bindEnv (flag .Lookup ("manifest-file" ), "PDD_MANIFEST_FILE" )
94+
95+ // backend variables
96+ bindEnv (flag .Lookup ("backend" ), "PDD_BACKEND" )
97+
98+ // backend - fs
99+ bindEnv (flag .Lookup ("filesystem-root" ), "PDD_FILESYSTEM_ROOT" )
100+
47101 // Parse Options
48102 if err := flag .Parse (os .Args ); err != nil {
49103 syslog .Fatalf ("%#v" , err )
@@ -68,6 +122,60 @@ func main() {
68122 }
69123
70124 logger .Debug ("version" , version , "git commit" , commit , "build date" , date )
125+
126+ // initialize db
127+ db , err := database .ConnectDB (logger , & dbc )
128+ if err != nil {
129+ logger .Error ("msg" , "failed to create database" , "error" , err )
130+ os .Exit (1 )
131+ }
132+
133+ // initialize dumper
134+ dumper , err := dump .NewDumper (logger , db , dc )
135+ if err != nil {
136+ logger .Error ("msg" , "failed to create dumper" , "error" , err )
137+ os .Exit (1 )
138+ }
139+
140+ // initialize backend
141+ b , err := backend .FromConfig (logger , bc )
142+ if err != nil {
143+ logger .Error ("msg" , "failed to create backend" , "error" , err )
144+ os .Exit (1 )
145+ }
146+
147+ // initialize storage
148+ s := storage .New (logger , b , storage .DefaultOperationTimeout )
149+
150+ if err := run (logger , dumper , s ); err != nil {
151+ logger .Error ("msg" , "failed to dump database" , "error" , err )
152+ os .Exit (1 )
153+ }
154+
155+ logger .Debug ("msg" , "export finished" )
156+ }
157+
158+ func run (logger log.Logger , dumper dump.Dumper , s storage.Storage ) error {
159+ // create a synchronous in-memory pipe.
160+ pr , pw := io .Pipe ()
161+
162+ defer helpers .CloseWithErrLogf (logger , pr , "dump error" )
163+
164+ go func () {
165+ defer helpers .CloseWithErrLogf (logger , pw , "dump error" )
166+
167+ if err := dumper .Dump (pw ); err != nil {
168+ logger .Error ("error" , err )
169+ }
170+ }()
171+
172+ return s .Put (generateFileName (), pr )
173+ }
174+
175+ // generateFileName generates new file name for dump based on timestamp.
176+ func generateFileName () string {
177+ t := time .Now ()
178+ return fmt .Sprintf ("dump-%s.sql" , t .Format ("20060102-150405" ))
71179}
72180
73181func bindEnv (fn * pflag.Flag , env string ) {
0 commit comments