root: config: implement config watching
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
parent
2a15004232
commit
969ec188a7
1
go.mod
1
go.mod
|
@ -42,6 +42,7 @@ require (
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
||||||
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
|
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
|
||||||
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
|
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -66,6 +66,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
github.com/garyburd/redigo v1.6.4 h1:LFu2R3+ZOPgSMWMOL+saa/zXRjw0ID2G8FepO53BGlg=
|
github.com/garyburd/redigo v1.6.4 h1:LFu2R3+ZOPgSMWMOL+saa/zXRjw0ID2G8FepO53BGlg=
|
||||||
github.com/garyburd/redigo v1.6.4/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw=
|
github.com/garyburd/redigo v1.6.4/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw=
|
||||||
github.com/getsentry/sentry-go v0.20.0 h1:bwXW98iMRIWxn+4FgPW7vMrjmbym6HblXALmhjHmQaQ=
|
github.com/getsentry/sentry-go v0.20.0 h1:bwXW98iMRIWxn+4FgPW7vMrjmbym6HblXALmhjHmQaQ=
|
||||||
|
@ -486,6 +488,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
|
@ -8,8 +8,10 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
env "github.com/Netflix/go-env"
|
env "github.com/Netflix/go-env"
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
@ -53,6 +55,71 @@ func getConfigPaths() []string {
|
||||||
return computedConfigPaths
|
return computedConfigPaths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WatchChanges(callback func()) (*fsnotify.Watcher, error) {
|
||||||
|
configPaths := getConfigPaths()
|
||||||
|
|
||||||
|
w, err := fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening for events
|
||||||
|
go func() {
|
||||||
|
reload := false
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
// Read from errors
|
||||||
|
case err, ok := <-w.Errors:
|
||||||
|
if !ok {
|
||||||
|
// Channel was closed (i.e. Watcher.Close() was called)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.WithError(err).Warning("failed to watch for file changes")
|
||||||
|
// Read from events
|
||||||
|
case ev, ok := <-w.Events:
|
||||||
|
if !ok {
|
||||||
|
// Channel was closed (i.e. Watcher.Close() was called)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignores files we're not interested in
|
||||||
|
// We get the whole list again in case a file in a directory we're watching was created
|
||||||
|
// and that file is of interest
|
||||||
|
for _, f := range getConfigPaths() {
|
||||||
|
if f == ev.Name {
|
||||||
|
reload = true
|
||||||
|
log.Debugf("%s file change, setting configuration to be reloaded", ev.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if reload {
|
||||||
|
log.Infof("configuration files changed, reloading configuration")
|
||||||
|
Reload()
|
||||||
|
callback()
|
||||||
|
// Cooldown after configuration reloading
|
||||||
|
time.Sleep(14 * time.Second)
|
||||||
|
}
|
||||||
|
// Otherwise `select` fires all of the time
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
reload = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Register the files to be watch
|
||||||
|
for _, p := range configPaths {
|
||||||
|
// Actually, watch the directory, not the files, as that's how fsnotify works
|
||||||
|
// We assume we're only getting valid files as getConfigPaths already handles all the necessary checks
|
||||||
|
err = w.Add(filepath.Dir(p))
|
||||||
|
log.Warningf("watching for changes for file %s in dir %s", p, filepath.Dir(p))
|
||||||
|
if err != nil {
|
||||||
|
return w, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return w, nil
|
||||||
|
}
|
||||||
|
|
||||||
func Get() *Config {
|
func Get() *Config {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
c := &Config{}
|
c := &Config{}
|
||||||
|
@ -62,6 +129,12 @@ func Get() *Config {
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Reload() {
|
||||||
|
c := &Config{}
|
||||||
|
c.Setup(getConfigPaths()...)
|
||||||
|
cfg = c
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) Setup(paths ...string) {
|
func (c *Config) Setup(paths ...string) {
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
err := c.LoadConfig(path)
|
err := c.LoadConfig(path)
|
||||||
|
|
Reference in a new issue