cmd/amazon-cloudwatch-agent-target-allocator/watcher/file.go (64 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package watcher
import (
"context"
"path/filepath"
"github.com/fsnotify/fsnotify"
"github.com/go-logr/logr"
promconfig "github.com/prometheus/prometheus/config"
"github.com/aws/amazon-cloudwatch-agent-operator/cmd/amazon-cloudwatch-agent-target-allocator/config"
)
var _ Watcher = &FileWatcher{}
type FileWatcher struct {
logger logr.Logger
configFilePath string
watcher *fsnotify.Watcher
closer chan bool
}
func NewFileWatcher(logger logr.Logger, configFilePath string) (*FileWatcher, error) {
fileWatcher, err := fsnotify.NewWatcher()
if err != nil {
logger.Error(err, "Can't start the watcher")
return &FileWatcher{}, err
}
return &FileWatcher{
logger: logger,
configFilePath: configFilePath,
watcher: fileWatcher,
closer: make(chan bool),
}, nil
}
func (f *FileWatcher) LoadConfig(_ context.Context) (*promconfig.Config, error) {
cfg := config.CreateDefaultConfig()
err := config.LoadFromFile(f.configFilePath, &cfg)
if err != nil {
f.logger.Error(err, "Unable to load configuration")
return nil, err
}
return cfg.PromConfig, nil
}
func (f *FileWatcher) Watch(upstreamEvents chan Event, upstreamErrors chan error) error {
err := f.watcher.Add(filepath.Dir(f.configFilePath))
if err != nil {
return err
}
for {
select {
case <-f.closer:
return nil
case fileEvent := <-f.watcher.Events:
// Using Op.Has as per this doc - https://github.com/fsnotify/fsnotify/blob/9342b6df577910c6eac718dc62845d8c95f8548b/fsnotify.go#L30
if fileEvent.Op.Has(fsnotify.Create) || fileEvent.Op.Has(fsnotify.Write) {
f.logger.Info("File change detected", "event", fileEvent.Op.String())
upstreamEvents <- Event{
Source: EventSourceConfigMap,
Watcher: Watcher(f),
}
}
case err := <-f.watcher.Errors:
upstreamErrors <- err
}
}
}
func (f *FileWatcher) Close() error {
f.closer <- true
return f.watcher.Close()
}