@@ -53,6 +53,9 @@ type DaemonCli struct {
5353 * daemon.Config
5454 commonFlags * cli.CommonFlags
5555 configFile * string
56+
57+ api * apiserver.Server
58+ d * daemon.Daemon
5659}
5760
5861func presentInHelp (usage string ) string { return usage }
@@ -121,7 +124,10 @@ func migrateKey() (err error) {
121124 return nil
122125}
123126
124- func (cli * DaemonCli ) start () {
127+ func (cli * DaemonCli ) start () (err error ) {
128+ stopc := make (chan bool )
129+ defer close (stopc )
130+
125131 // warn from uuid package when running the daemon
126132 uuid .Loggerf = logrus .Warnf
127133
@@ -133,8 +139,7 @@ func (cli *DaemonCli) start() {
133139 }
134140 cliConfig , err := loadDaemonCliConfig (cli .Config , flags , cli .commonFlags , * cli .configFile )
135141 if err != nil {
136- fmt .Fprint (os .Stderr , err )
137- os .Exit (1 )
142+ return err
138143 }
139144 cli .Config = cliConfig
140145
@@ -152,24 +157,22 @@ func (cli *DaemonCli) start() {
152157 })
153158
154159 if err := setDefaultUmask (); err != nil {
155- logrus . Fatalf ("Failed to set umask: %v" , err )
160+ return fmt . Errorf ("Failed to set umask: %v" , err )
156161 }
157162
158163 if len (cli .LogConfig .Config ) > 0 {
159164 if err := logger .ValidateLogOpts (cli .LogConfig .Type , cli .LogConfig .Config ); err != nil {
160- logrus . Fatalf ("Failed to set log opts: %v" , err )
165+ return fmt . Errorf ("Failed to set log opts: %v" , err )
161166 }
162167 }
163168
164- var pfile * pidfile.PIDFile
165169 if cli .Pidfile != "" {
166170 pf , err := pidfile .New (cli .Pidfile )
167171 if err != nil {
168- logrus . Fatalf ("Error starting daemon: %v" , err )
172+ return fmt . Errorf ("Error starting daemon: %v" , err )
169173 }
170- pfile = pf
171174 defer func () {
172- if err := pfile .Remove (); err != nil {
175+ if err := pf .Remove (); err != nil {
173176 logrus .Error (err )
174177 }
175178 }()
@@ -196,7 +199,7 @@ func (cli *DaemonCli) start() {
196199 }
197200 tlsConfig , err := tlsconfig .Server (tlsOptions )
198201 if err != nil {
199- logrus . Fatal ( err )
202+ return err
200203 }
201204 serverConfig .TLSConfig = tlsConfig
202205 }
@@ -210,13 +213,13 @@ func (cli *DaemonCli) start() {
210213 for i := 0 ; i < len (cli .Config .Hosts ); i ++ {
211214 var err error
212215 if cli .Config .Hosts [i ], err = opts .ParseHost (cli .Config .TLS , cli .Config .Hosts [i ]); err != nil {
213- logrus . Fatalf ("error parsing -H %s : %v" , cli .Config .Hosts [i ], err )
216+ return fmt . Errorf ("error parsing -H %s : %v" , cli .Config .Hosts [i ], err )
214217 }
215218
216219 protoAddr := cli .Config .Hosts [i ]
217220 protoAddrParts := strings .SplitN (protoAddr , "://" , 2 )
218221 if len (protoAddrParts ) != 2 {
219- logrus . Fatalf ("bad format %s, expected PROTO://ADDR" , protoAddr )
222+ return fmt . Errorf ("bad format %s, expected PROTO://ADDR" , protoAddr )
220223 }
221224
222225 proto := protoAddrParts [0 ]
@@ -228,37 +231,32 @@ func (cli *DaemonCli) start() {
228231 }
229232 l , err := listeners .Init (proto , addr , serverConfig .SocketGroup , serverConfig .TLSConfig )
230233 if err != nil {
231- logrus . Fatal ( err )
234+ return err
232235 }
233236 // If we're binding to a TCP port, make sure that a container doesn't try to use it.
234237 if proto == "tcp" {
235238 if err := allocateDaemonPort (addr ); err != nil {
236- logrus . Fatal ( err )
239+ return err
237240 }
238241 }
239242 logrus .Debugf ("Listener created for HTTP on %s (%s)" , protoAddrParts [0 ], protoAddrParts [1 ])
240243 api .Accept (protoAddrParts [1 ], l ... )
241244 }
242245
243246 if err := migrateKey (); err != nil {
244- logrus . Fatal ( err )
247+ return err
245248 }
246249 cli .TrustKeyPath = cli .commonFlags .TrustKey
247250
248251 registryService := registry .NewService (cli .Config .ServiceOptions )
249252 containerdRemote , err := libcontainerd .New (cli .getLibcontainerdRoot (), cli .getPlatformRemoteOptions ()... )
250253 if err != nil {
251- logrus . Fatal ( err )
254+ return err
252255 }
253256
254257 d , err := daemon .NewDaemon (cli .Config , registryService , containerdRemote )
255258 if err != nil {
256- if pfile != nil {
257- if err := pfile .Remove (); err != nil {
258- logrus .Error (err )
259- }
260- }
261- logrus .Fatalf ("Error starting daemon: %v" , err )
259+ return fmt .Errorf ("Error starting daemon: %v" , err )
262260 }
263261
264262 logrus .Info ("Daemon has completed initialization" )
@@ -272,26 +270,9 @@ func (cli *DaemonCli) start() {
272270 cli .initMiddlewares (api , serverConfig )
273271 initRouter (api , d )
274272
275- reload := func (config * daemon.Config ) {
276- if err := d .Reload (config ); err != nil {
277- logrus .Errorf ("Error reconfiguring the daemon: %v" , err )
278- return
279- }
280- if config .IsValueSet ("debug" ) {
281- debugEnabled := utils .IsDebugEnabled ()
282- switch {
283- case debugEnabled && ! config .Debug : // disable debug
284- utils .DisableDebug ()
285- api .DisableProfiler ()
286- case config .Debug && ! debugEnabled : // enable debug
287- utils .EnableDebug ()
288- api .EnableProfiler ()
289- }
290-
291- }
292- }
293-
294- setupConfigReloadTrap (* cli .configFile , flags , reload )
273+ cli .d = d
274+ cli .api = api
275+ cli .setupConfigReloadTrap ()
295276
296277 // The serve API routine never exits unless an error occurs
297278 // We need to start it as a goroutine and wait on it so
@@ -300,14 +281,8 @@ func (cli *DaemonCli) start() {
300281 go api .Wait (serveAPIWait )
301282
302283 signal .Trap (func () {
303- api .Close ()
304- <- serveAPIWait
305- shutdownDaemon (d , 15 )
306- if pfile != nil {
307- if err := pfile .Remove (); err != nil {
308- logrus .Error (err )
309- }
310- }
284+ cli .stop ()
285+ <- stopc // wait for daemonCli.start() to return
311286 })
312287
313288 // after the daemon is done setting up we can notify systemd api
@@ -319,13 +294,39 @@ func (cli *DaemonCli) start() {
319294 shutdownDaemon (d , 15 )
320295 containerdRemote .Cleanup ()
321296 if errAPI != nil {
322- if pfile != nil {
323- if err := pfile .Remove (); err != nil {
324- logrus .Error (err )
297+ return fmt .Errorf ("Shutting down due to ServeAPI error: %v" , errAPI )
298+ }
299+
300+ return nil
301+ }
302+
303+ func (cli * DaemonCli ) reloadConfig () {
304+ reload := func (config * daemon.Config ) {
305+ if err := cli .d .Reload (config ); err != nil {
306+ logrus .Errorf ("Error reconfiguring the daemon: %v" , err )
307+ return
308+ }
309+ if config .IsValueSet ("debug" ) {
310+ debugEnabled := utils .IsDebugEnabled ()
311+ switch {
312+ case debugEnabled && ! config .Debug : // disable debug
313+ utils .DisableDebug ()
314+ cli .api .DisableProfiler ()
315+ case config .Debug && ! debugEnabled : // enable debug
316+ utils .EnableDebug ()
317+ cli .api .EnableProfiler ()
325318 }
319+
326320 }
327- logrus .Fatalf ("Shutting down due to ServeAPI error: %v" , errAPI )
328321 }
322+
323+ if err := daemon .ReloadConfiguration (* cli .configFile , flag .CommandLine , reload ); err != nil {
324+ logrus .Error (err )
325+ }
326+ }
327+
328+ func (cli * DaemonCli ) stop () {
329+ cli .api .Close ()
329330}
330331
331332// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
0 commit comments