mirror of
https://github.com/slackhq/nebula.git
synced 2026-11-15 11:26:52 +01:00
99 lines
3.0 KiB
Go
99 lines
3.0 KiB
Go
package config
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"slices"
|
|
)
|
|
|
|
// ReloadResult describes how a reload went. Problems are logged where they happen, Log writes a one line summary.
|
|
type ReloadResult struct {
|
|
// Err is set when the new config could not be read or parsed, no callbacks ran
|
|
Err error
|
|
// Failed is true when a callback could not apply part of the new config
|
|
Failed bool
|
|
// RestartRequired is true once any reload has needed a restart, and stays true until the process restarts
|
|
RestartRequired bool
|
|
// RestartKeys are the keys this reload changed that only apply on a restart
|
|
RestartKeys []string
|
|
}
|
|
|
|
// Summary returns a one line summary of the reload and the level to log it at.
|
|
func (r ReloadResult) Summary() (slog.Level, string) {
|
|
switch {
|
|
case r.Err != nil && r.RestartRequired:
|
|
return slog.LevelError, "Config reload failed, the new config did not load and a restart is still required"
|
|
case r.Err != nil:
|
|
return slog.LevelError, "Config reload failed, the new config did not load"
|
|
case r.Failed && r.RestartRequired:
|
|
return slog.LevelError, "Config reload completed with errors and requires a restart to fully apply, review the logs"
|
|
case r.Failed:
|
|
return slog.LevelError, "Config reload completed with errors, review the logs"
|
|
case r.RestartRequired:
|
|
return slog.LevelWarn, "Config reload was completed but requires a restart to fully apply"
|
|
default:
|
|
return slog.LevelInfo, "Config reload complete"
|
|
}
|
|
}
|
|
|
|
// String is the summary with Err and RestartKeys included, for output other than the log.
|
|
func (r ReloadResult) String() string {
|
|
_, msg := r.Summary()
|
|
if r.Err != nil {
|
|
msg = fmt.Sprintf("%s: %v", msg, r.Err)
|
|
}
|
|
if len(r.RestartKeys) > 0 {
|
|
msg = fmt.Sprintf("%s, keys %v", msg, r.RestartKeys)
|
|
}
|
|
return msg
|
|
}
|
|
|
|
// Log writes Summary to l.
|
|
func (r ReloadResult) Log(l *slog.Logger) {
|
|
level, msg := r.Summary()
|
|
if len(r.RestartKeys) > 0 {
|
|
l.Log(context.Background(), level, msg, "keys", r.RestartKeys)
|
|
return
|
|
}
|
|
l.Log(context.Background(), level, msg)
|
|
}
|
|
|
|
// Reload is passed to each reload callback to report how applying the new config went.
|
|
type Reload struct {
|
|
c *C
|
|
failed bool
|
|
restart bool
|
|
// Changed keys that only apply on a restart, from every callback
|
|
keys []string
|
|
}
|
|
|
|
// Failed marks the reload as failed, the caller logs why. Safe to call on a nil Reload, which is what the initial load
|
|
// passes.
|
|
func (r *Reload) Failed() {
|
|
if r != nil {
|
|
r.failed = true
|
|
}
|
|
}
|
|
|
|
// RestartRequired marks the reload as needing a restart, the caller logs why. Safe to call on a nil Reload.
|
|
func (r *Reload) RestartRequired() {
|
|
if r != nil {
|
|
r.restart = true
|
|
}
|
|
}
|
|
|
|
// RestartRequiredIfChanged marks the reload as needing a restart if any of keys changed, and adds them to RestartKeys.
|
|
// Use it for keys that are only read at startup. Safe to call on a nil Reload.
|
|
func (r *Reload) RestartRequiredIfChanged(keys ...string) {
|
|
if r == nil {
|
|
return
|
|
}
|
|
for _, k := range keys {
|
|
if r.c.HasChanged(k) && !slices.Contains(r.keys, k) {
|
|
r.keys = append(r.keys, k)
|
|
r.restart = true
|
|
}
|
|
}
|
|
}
|