v0.2.5: Reloading a badly formated configuration wont crash, so the old configuration will keep running.

This commit is contained in:
yo 2025-01-13 20:15:32 +01:00
parent fe6ca819f4
commit 8958845f65

58
main.go
View File

@ -34,7 +34,7 @@ import (
)
const (
gVersion = "0.2.4"
gVersion = "0.2.5"
// Default datasource timeout is 10 seconds
gDefaultDSTimeout = 10
)
@ -329,7 +329,7 @@ func getGraph(name string) (Graph, error) {
return Graph{}, fmt.Errorf("Graph not found: %s", name)
}
func initRoutes(r *gin.Engine) {
func initRoutes(r *gin.Engine, confFile string) {
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
@ -338,7 +338,10 @@ func initRoutes(r *gin.Engine) {
// An endpoint to force read of configuration file
r.POST("/reload", func(c *gin.Context) {
reloadConfigFile()
if err := reloadConfigFile(confFile); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "configuration successfully reloaded",
})
@ -469,16 +472,32 @@ func newEdgeClone(src *Edge) *Edge {
}
}
func reloadConfigFile() {
// First reread config file
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
log.Fatalf("config file not found")
os.Exit(1)
// This function assume we already have a running configuration.
func reloadConfigFile(confFile string) error {
oldConfigRestored := false
// We need to keep this config, incase the new one is b0rken
fname := fmt.Sprintf("/tmp/nodegopher.%d.yaml", os.Getpid())
if err := viper.WriteConfigAs(fname); err != nil {
log.Errorf("Unable to save current running config to %s, wont reload configuration.\n", fname)
return fmt.Errorf("Unable to save current configuration, configuration not reloaded. See logs.")
}
defer os.Remove(fname)
// Reread config file
if oldErr := viper.ReadInConfig(); oldErr != nil {
if _, ok := oldErr.(viper.ConfigFileNotFoundError); ok {
log.Errorf("config file not found")
} else {
log.Fatalf("unknown error looking for config file: %v", err)
os.Exit(1)
log.Errorf("unknown error looking for config file: %v", oldErr)
}
// Restore old configuration and notify.
log.Debugf("Fallback on previous configuration.\n")
viper.SetConfigFile(fname)
if err := viper.ReadInConfig(); err != nil {
log.Fatalf("Unable to restore configuration, and new is invalid. fix it now.\n")
}
viper.SetConfigFile(confFile)
oldConfigRestored = true
}
switch viper.Get("language").(string) {
@ -503,6 +522,7 @@ func reloadConfigFile() {
gCfgMutex.Lock()
defer gCfgMutex.Unlock()
// We need to keep this config, incase the new one is b0rken
for _, g := range gGraphs {
g.Nodes = nil
g.Edges = nil
@ -538,8 +558,8 @@ func reloadConfigFile() {
}
if viper.Get("datasources") == nil {
log.Printf("no datasources found, data will be static")
return
log.Warningf("no datasources found, data will be static")
return nil
}
dss := viper.Get("datasources").([]interface{})
for _, d := range dss {
@ -552,6 +572,10 @@ func reloadConfigFile() {
}
gDataSources = append(gDataSources, ds)
}
if oldConfigRestored {
return fmt.Errorf("Unable to load new configuration, keeping old one. See logs.")
}
return nil
}
func main() {
@ -604,7 +628,7 @@ func main() {
// FIXME: Watch config changes. Does not work on FreeBSD. TODO: Test with linux
viper.OnConfigChange(func(e fsnotify.Event) {
log.Printf("Config file changed, reloading data\n")
reloadConfigFile()
reloadConfigFile(confFile)
})
// Lets reload config on SIGHUP
@ -614,11 +638,11 @@ func main() {
for {
_ = <- sigs
log.Infof("SIGHUP received, reloading configuration\n")
reloadConfigFile()
reloadConfigFile(confFile)
}
}()
reloadConfigFile()
reloadConfigFile(confFile)
// Capture variable name. There should be only one variable. Space is tolerated before and after name.
gDSVarCompRegex = regexp.MustCompile(`^\{\{(?:\ )?([a-zA-Z0-9\-_]+)(?:\ )?\}\}$`)
@ -629,6 +653,6 @@ func main() {
log.Printf("Starting NodeGopher v.%s\n", gVersion)
r := gin.Default()
initRoutes(r)
initRoutes(r, confFile)
r.Run(listen)
}