func WatchConfig()

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
}