replaceLocalAdminServer replaces the running local admin server according to the relevant configuration in cfg. If no configuration for the admin endpoint exists in cfg, a default one is used, so that there is always an admin server (unless it is explicitly configured to be disabled). Critically not
(cfg *Config, ctx Context)
| 372 | // Critically note that some elements and functionality of the context |
| 373 | // may not be ready, e.g. storage. Tread carefully. |
| 374 | func replaceLocalAdminServer(cfg *Config, ctx Context) error { |
| 375 | // always* be sure to close down the old admin endpoint |
| 376 | // as gracefully as possible, even if the new one is |
| 377 | // disabled -- careful to use reference to the current |
| 378 | // (old) admin endpoint since it will be different |
| 379 | // when the function returns |
| 380 | // (* except if the new one fails to start) |
| 381 | oldAdminServer := localAdminServer |
| 382 | var err error |
| 383 | defer func() { |
| 384 | // do the shutdown asynchronously so that any |
| 385 | // current API request gets a response; this |
| 386 | // goroutine may last a few seconds |
| 387 | if oldAdminServer != nil && err == nil { |
| 388 | go func(oldAdminServer *http.Server) { |
| 389 | err := stopAdminServer(oldAdminServer) |
| 390 | if err != nil { |
| 391 | Log().Named("admin").Error("stopping current admin endpoint", zap.Error(err)) |
| 392 | } |
| 393 | }(oldAdminServer) |
| 394 | } |
| 395 | }() |
| 396 | |
| 397 | // set a default if admin wasn't otherwise configured |
| 398 | if cfg.Admin == nil { |
| 399 | cfg.Admin = &AdminConfig{ |
| 400 | Listen: DefaultAdminListen, |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | // if new admin endpoint is to be disabled, we're done |
| 405 | if cfg.Admin.Disabled { |
| 406 | Log().Named("admin").Warn("admin endpoint disabled") |
| 407 | return nil |
| 408 | } |
| 409 | |
| 410 | // extract a singular listener address |
| 411 | addr, err := parseAdminListenAddr(cfg.Admin.Listen, DefaultAdminListen) |
| 412 | if err != nil { |
| 413 | return err |
| 414 | } |
| 415 | |
| 416 | handler, err := cfg.Admin.newAdminHandler(addr, false, ctx) |
| 417 | if err != nil { |
| 418 | return err |
| 419 | } |
| 420 | |
| 421 | ln, err := addr.Listen(context.TODO(), 0, net.ListenConfig{}) |
| 422 | if err != nil { |
| 423 | return err |
| 424 | } |
| 425 | |
| 426 | serverMu.Lock() |
| 427 | localAdminServer = &http.Server{ |
| 428 | Addr: addr.String(), // for logging purposes only |
| 429 | Handler: handler, |
| 430 | ReadTimeout: 10 * time.Second, |
| 431 | ReadHeaderTimeout: 5 * time.Second, |
no test coverage detected