1111package main
1212
1313import (
14- "bytes"
1514 "context"
15+ "os"
16+ "os/signal"
17+ "syscall"
1618
1719 "github.com/docker/docker/client"
18- "github.com/jessevdk/go-flags"
1920 "github.com/pkg/errors"
2021 "github.com/rs/xid"
2122
@@ -31,57 +32,18 @@ import (
3132 "gitlab.com/postgres-ai/database-lab/version"
3233)
3334
34- var opts struct {
35- VerificationToken string `short:"t" long:"token" description:"API verification token" env:"VERIFICATION_TOKEN"`
36-
37- MountDir string `long:"mount-dir" description:"clones data mount directory" env:"MOUNT_DIR"`
38- UnixSocketDir string `long:"sockets-dir" description:"unix sockets directory for secure connection to clones" env:"UNIX_SOCKET_DIR"`
39- DockerImage string `long:"docker-image" description:"clones Docker image" env:"DOCKER_IMAGE"`
40-
41- ShowHelp func () error `long:"help" description:"Show this help message"`
42- }
43-
4435func main () {
4536 log .Msg ("Database Lab version: " , version .GetVersion ())
4637
47- // Load CLI options.
48- if _ , err := parseArgs (); err != nil {
49- if flags .WroteHelp (err ) {
50- return
51- }
38+ instanceID := xid .New ().String ()
5239
53- log .Fatal ("Args parse error:" , err )
54- }
40+ log .Msg ("Database Lab Instance ID:" , instanceID )
5541
56- cfg , err := config . LoadConfig ( "config.yml" )
42+ cfg , err := loadConfiguration ( instanceID )
5743 if err != nil {
5844 log .Fatalf (errors .WithMessage (err , "failed to parse config" ))
5945 }
6046
61- log .DEBUG = cfg .Global .Debug
62- log .Dbg ("Config loaded" , cfg )
63-
64- // TODO(anatoly): Annotate envs in configs. Use different lib for flags/configs?
65- if len (opts .MountDir ) > 0 {
66- cfg .Provision .Options .ClonesMountDir = opts .MountDir
67- }
68-
69- if len (opts .UnixSocketDir ) > 0 {
70- cfg .Provision .Options .UnixSocketDir = opts .UnixSocketDir
71- }
72-
73- if len (opts .DockerImage ) > 0 {
74- cfg .Provision .Options .DockerImage = opts .DockerImage
75- }
76-
77- if cfg .Provision .Options .ClonesMountDir != "" {
78- cfg .Global .ClonesMountDir = cfg .Provision .Options .ClonesMountDir
79- }
80-
81- cfg .Global .InstanceID = xid .New ().String ()
82-
83- log .Msg ("Database Lab Instance ID" , cfg .Global .InstanceID )
84-
8547 ctx , cancel := context .WithCancel (context .Background ())
8648 defer cancel ()
8749
@@ -121,40 +83,73 @@ func main() {
12183 log .Fatalf (errors .WithMessage (err , "failed to create a new platform service" ))
12284 }
12385
124- if len (opts .VerificationToken ) > 0 {
125- cfg .Server .VerificationToken = opts .VerificationToken
126- }
127-
12886 observerCfg := & observer.Config {
12987 CloneDir : cfg .Provision .Options .ClonesMountDir ,
13088 DataSubDir : cfg .Global .DataSubDir ,
13189 SocketDir : cfg .Provision .Options .UnixSocketDir ,
13290 }
13391
134- // Start the Database Lab.
13592 server := srv .NewServer (& cfg .Server , observerCfg , cloningSvc , platformSvc , dockerCLI )
93+
94+ c := make (chan os.Signal , 1 )
95+ signal .Notify (c , syscall .SIGHUP )
96+
97+ go func () {
98+ for range c {
99+ log .Msg ("Reloading configuration" )
100+
101+ if err := reloadConfig (instanceID , provisionSvc , retrievalSvc , cloningSvc , platformSvc , server ); err != nil {
102+ log .Err ("Failed to reload configuration" , err )
103+ }
104+
105+ log .Msg ("Configuration has been reloaded" )
106+ }
107+ }()
108+
109+ // Start the Database Lab.
136110 if err = server .Run (); err != nil {
137111 log .Fatalf (err )
138112 }
139113}
140114
141- func parseArgs () ([]string , error ) {
142- var parser = flags .NewParser (& opts , flags .Default & ^ flags .HelpFlag )
115+ func loadConfiguration (instanceID string ) (* config.Config , error ) {
116+ cfg , err := config .LoadConfig ("config.yml" )
117+ if err != nil {
118+ return nil , errors .Wrap (err , "failed to parse config" )
119+ }
143120
144- // jessevdk/go-flags lib doesn't allow to use short flag -h because
145- // it's binded to usage help. We need to hack it a bit to use -h
146- // for as a hostname option.
147- // See https://github.com/jessevdk/go-flags/issues/240
148- opts .ShowHelp = func () error {
149- var b bytes.Buffer
121+ log .DEBUG = cfg .Global .Debug
122+ log .Dbg ("Config loaded" , cfg )
150123
151- parser .WriteHelp (& b )
124+ if cfg .Provision .Options .ClonesMountDir != "" {
125+ cfg .Global .ClonesMountDir = cfg .Provision .Options .ClonesMountDir
126+ }
152127
153- return & flags.Error {
154- Type : flags .ErrHelp ,
155- Message : b .String (),
156- }
128+ cfg .Global .InstanceID = instanceID
129+
130+ return cfg , nil
131+ }
132+
133+ func reloadConfig (instanceID string , provisionSvc provision.Provision , retrievalSvc * retrieval.Retrieval , cloningSvc cloning.Cloning ,
134+ platformSvc * platform.Service , server * srv.Server ) error {
135+ cfg , err := loadConfiguration (instanceID )
136+ if err != nil {
137+ return err
138+ }
139+
140+ if err := provision .IsValidConfig (cfg .Provision ); err != nil {
141+ return err
157142 }
158143
159- return parser .Parse ()
144+ if err := retrieval .IsValidConfig (cfg ); err != nil {
145+ return err
146+ }
147+
148+ provisionSvc .Reload (cfg .Provision )
149+ retrievalSvc .Reload (cfg )
150+ cloningSvc .Reload (cfg .Cloning )
151+ platformSvc .Reload (cfg .Platform )
152+ server .Reload (cfg .Server )
153+
154+ return nil
160155}
0 commit comments