in lib/config.go [122:188]
func WatchConfig(
configPath, overridesPath string, version int, provider ConfigProvider,
) (chan *Config, error) {
configChan := make(chan *Config)
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
// strings containing the real path of a config files, if they are symlinks
var realConfigPath string
var realOverridesPath string
err = watcher.Add(filepath.Dir(configPath))
if err != nil {
return nil, err
}
realConfigPath, err = filepath.EvalSymlinks(configPath)
if err == nil {
// configPath is a symlink, also watch the pointee
err = watcher.Add(realConfigPath)
}
// setup watcher on overrides file if present
if len(overridesPath) > 0 {
err = watcher.Add(filepath.Dir(overridesPath))
if err != nil {
glog.Errorf("Failed to start fsnotify on overrides config file: %s", err)
return nil, err
}
realOverridesPath, err = filepath.EvalSymlinks(overridesPath)
if err == nil {
// overridesPath is a symlink, also watch the pointee
err = watcher.Add(realOverridesPath)
}
}
// watch for fsnotify events
go func() {
for {
select {
case ev := <-watcher.Events:
// ignore Remove events
if ev.Op&fsnotify.Remove == fsnotify.Remove {
continue
}
// only care about symlinks and target of symlinks
if ev.Name == overridesPath || ev.Name == configPath ||
ev.Name == realOverridesPath || ev.Name == realConfigPath {
glog.Infof("Configuration file changed (%s), reloading", ev)
config, err := LoadConfig(
configPath, overridesPath, version, provider)
if err != nil {
glog.Fatalf("Failed to reload config: %s", err)
panic(err) // fail hard
}
configChan <- config
}
case err := <-watcher.Errors:
glog.Errorf("fsnotify error: %s", err)
}
}
}()
return configChan, nil
}