This commit is contained in:
Caleb Doxsey 2023-11-02 12:46:59 -06:00
parent 032dd812ed
commit 68910c6064
2 changed files with 43 additions and 22 deletions

View file

@ -16,6 +16,7 @@ import (
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/telemetry/metrics"
"github.com/pomerium/pomerium/pkg/netutil"
"github.com/pomerium/pomerium/pkg/slices"
)
// A ChangeListener is called when configuration changes.
@ -132,7 +133,9 @@ func NewFileOrEnvironmentSource(
watcher: fileutil.NewWatcher(),
config: cfg,
}
src.watcher.Watch(ctx, []string{configFile})
if configFile != "" {
src.watcher.Watch(ctx, []string{configFile})
}
ch := src.watcher.Bind()
go func() {
for range ch {
@ -227,6 +230,8 @@ func (src *FileWatcherSource) onConfigChange(ctx context.Context, cfg *Config) {
// store the config and trigger an update
src.cfg = cfg.Clone()
src.hash = getAllConfigFilePathsHash(src.cfg)
log.Info(ctx).Uint64("hash", src.hash).Msg("config/filewatchersource: underlying config change, triggering update")
src.Trigger(ctx, src.cfg)
}
@ -234,9 +239,23 @@ func (src *FileWatcherSource) onFileChange(ctx context.Context) {
src.mu.Lock()
defer src.mu.Unlock()
hash := getAllConfigFilePathsHash(src.cfg)
if hash == src.hash {
log.Info(ctx).Uint64("hash", src.hash).Msg("config/filewatchersource: no change detected")
} else {
// if the hash changed, trigger an update
// the actual config will be identical
src.hash = hash
log.Info(ctx).Uint64("hash", src.hash).Msg("config/filewatchersource: change detected, triggering update")
src.Trigger(ctx, src.cfg)
}
}
func getAllConfigFilePathsHash(cfg *Config) uint64 {
// read all the config files and build a hash from their contents
h := xxhash.New()
for _, f := range getAllConfigFilePaths(src.cfg) {
for _, f := range getAllConfigFilePaths(cfg) {
_, _ = h.Write([]byte{0})
f, err := os.Open(f)
if err == nil {
@ -244,17 +263,7 @@ func (src *FileWatcherSource) onFileChange(ctx context.Context) {
_ = f.Close()
}
}
hash := h.Sum64()
if hash == src.hash {
log.Info(ctx).Msg("config/filewatchersource: no change detected")
} else {
// if the hash changed, trigger an update
// the actual config will be identical
log.Info(ctx).Msg("config/filewatchersource: change detected")
src.hash = hash
src.Trigger(ctx, src.cfg)
}
return h.Sum64()
}
func getAllConfigFilePaths(cfg *Config) []string {
@ -292,5 +301,9 @@ func getAllConfigFilePaths(cfg *Config) []string {
)
}
fs = slices.Filter(fs, func(s string) bool {
return s != ""
})
return fs
}

View file

@ -54,29 +54,37 @@ func (watcher *Watcher) Watch(ctx context.Context, filePaths []string) {
}
for _, filePath := range add {
watcher.watching[filePath] = struct{}{}
if watcher.eventWatcher != nil {
if err := watcher.eventWatcher.Add(filePath); err != nil {
log.Error(ctx).Msg("fileutil/watcher: failed to add file to event-based file watcher")
err := watcher.eventWatcher.Add(filePath)
if err != nil {
log.Error(ctx).Err(err).Str("file", filePath).Msg("fileutil/watcher: failed to add file to polling-based file watcher")
}
}
if watcher.pollingWatcher != nil {
if err := watcher.pollingWatcher.Add(filePath); err != nil {
log.Error(ctx).Msg("fileutil/watcher: failed to add file to polling-based file watcher")
err := watcher.pollingWatcher.Add(filePath)
if err != nil {
log.Error(ctx).Err(err).Str("file", filePath).Msg("fileutil/watcher: failed to add file to polling-based file watcher")
}
}
}
for _, filePath := range remove {
delete(watcher.watching, filePath)
if watcher.eventWatcher != nil {
if err := watcher.eventWatcher.Remove(filePath); err != nil {
log.Error(ctx).Msg("fileutil/watcher: failed to remove file from event-based file watcher")
err := watcher.eventWatcher.Remove(filePath)
if err != nil {
log.Error(ctx).Err(err).Str("file", filePath).Msg("fileutil/watcher: failed to remove file from event-based file watcher")
}
}
if watcher.pollingWatcher != nil {
if err := watcher.pollingWatcher.Remove(filePath); err != nil {
log.Error(ctx).Msg("fileutil/watcher: failed to remove file from polling-based file watcher")
err := watcher.pollingWatcher.Remove(filePath)
if err != nil {
log.Error(ctx).Err(err).Str("file", filePath).Msg("fileutil/watcher: failed to remove file from polling-based file watcher")
}
}
}
@ -91,7 +99,7 @@ func (watcher *Watcher) initLocked(ctx context.Context) {
var err error
watcher.eventWatcher, err = filenotify.NewEventWatcher()
if err != nil {
log.Error(ctx).Msg("fileutil/watcher: failed to create event-based file watcher")
log.Error(ctx).Err(err).Msg("fileutil/watcher: failed to create event-based file watcher")
}
}
if watcher.pollingWatcher == nil {