Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ require (
github.com/gorilla/mux v1.8.0
github.com/lib/pq v1.10.9
github.com/oschwald/geoip2-golang v1.9.0
github.com/slack-go/slack v0.12.2
gorm.io/driver/postgres v1.5.2
github.com/slack-go/slack v0.12.2
github.com/fsnotify/fsnotify v1.6.0
gorm.io/driver/postgres v1.5.2
gorm.io/gorm v1.25.4
)

Expand Down
84 changes: 75 additions & 9 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"io"
"log"
"os"
"path/filepath"
"sync"

"github.com/fsnotify/fsnotify"

Check failure on line 11 in pkg/config/config.go

View workflow job for this annotation

GitHub Actions / Build

missing go.sum entry for module providing package github.com/fsnotify/fsnotify (imported by shadowguard/pkg/config); to add:
)

// PluginConfig represents the configuration for a single plugin
Expand Down Expand Up @@ -37,6 +41,69 @@
Endpoints []Endpoint `json:"endpoints"`
}

var (
current *Config
mu sync.RWMutex
)

func loadConfigFromFile(path string) (*Config, error) {
configJsonFile, err := os.Open(path)
if err != nil {
return nil, err
}
defer configJsonFile.Close()

byteData, err := io.ReadAll(configJsonFile)
if err != nil {
return nil, err
}

var cfg Config
if err := json.Unmarshal(byteData, &cfg); err != nil {
return nil, err
}
return &cfg, nil
}

func watchConfigFile(path string) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Printf("Error creating watcher: %v", err)
return
}
defer watcher.Close()

dir := filepath.Dir(path)
if err := watcher.Add(dir); err != nil {
log.Printf("Error watching config directory: %v", err)
return
}

for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Op&(fsnotify.Write|fsnotify.Create) != 0 && filepath.Clean(event.Name) == filepath.Clean(path) {
log.Printf("Configuration file changed. Reloading\n")
if cfg, err := loadConfigFromFile(path); err != nil {
log.Printf("Failed to reload configuration: %v", err)
} else {
mu.Lock()
*current = *cfg
mu.Unlock()
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Printf("Watcher error: %v", err)
}
}
}

// Init initializes the configuration from a file.
// The config file path can be set dynamically using environment variables.
// The default is assumed to be `config.json` in the same directory.
Expand All @@ -47,18 +114,17 @@
}

log.Printf("Reading configuration file %s\n", configFilePath)
configJsonFile, err := os.Open(configFilePath)
if err != nil {
panic(err)
}
defer configJsonFile.Close()
byteData, err := io.ReadAll(configJsonFile)
cfg, err := loadConfigFromFile(configFilePath)
if err != nil {
panic(err)
}

var config Config
json.Unmarshal(byteData, &config)
mu.Lock()
current = cfg
mu.Unlock()

go watchConfigFile(configFilePath)

log.Printf("Configuration file loaded.\n")
return &config
return current
}
Loading