v0.2.5: Reloading a badly formated configuration wont crash, so the old configuration will keep running.
This commit is contained in:
parent
fe6ca819f4
commit
8958845f65
60
main.go
60
main.go
@ -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)
|
||||
} else {
|
||||
log.Fatalf("unknown error looking for config file: %v", err)
|
||||
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.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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user