mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 00:19:57 +00:00
AUTH-2587 add config watcher and reload logic for access client forwarder
This commit is contained in:
58
watcher/file.go
Normal file
58
watcher/file.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package watcher
|
||||
|
||||
import (
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
// File is a file watcher that notifies when a file has been changed
|
||||
type File struct {
|
||||
watcher *fsnotify.Watcher
|
||||
shutdown chan struct{}
|
||||
}
|
||||
|
||||
// NewFile is a standard constructor
|
||||
func NewFile() (*File, error) {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f := &File{
|
||||
watcher: watcher,
|
||||
shutdown: make(chan struct{}),
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Add adds a file to start watching
|
||||
func (f *File) Add(filepath string) error {
|
||||
return f.watcher.Add(filepath)
|
||||
}
|
||||
|
||||
// Shutdown stop the file watching run loop
|
||||
func (f *File) Shutdown() {
|
||||
f.shutdown <- struct{}{}
|
||||
}
|
||||
|
||||
// Start is a runloop to watch for files changes from the file paths added from Add()
|
||||
func (f *File) Start(notifier Notification) {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-f.watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||
notifier.WatcherItemDidChange(event.Name)
|
||||
}
|
||||
case err, ok := <-f.watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
notifier.WatcherDidError(err)
|
||||
|
||||
case <-f.shutdown:
|
||||
f.watcher.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
54
watcher/file_test.go
Normal file
54
watcher/file_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package watcher
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type mockNotifier struct {
|
||||
eventPath string
|
||||
}
|
||||
|
||||
func (n *mockNotifier) WatcherItemDidChange(path string) {
|
||||
n.eventPath = path
|
||||
}
|
||||
|
||||
func (n *mockNotifier) WatcherDidError(err error) {
|
||||
}
|
||||
|
||||
func TestFileChanged(t *testing.T) {
|
||||
filePath := "test_file"
|
||||
f, err := os.Create(filePath)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
f.Close()
|
||||
os.Remove(filePath)
|
||||
}()
|
||||
|
||||
service, err := NewFile()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = service.Add(filePath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
n := &mockNotifier{}
|
||||
go service.Start(n)
|
||||
|
||||
f.Sync()
|
||||
|
||||
w := bufio.NewWriter(f)
|
||||
_, err = w.WriteString("hello Austin, do you like my file watcher?\n")
|
||||
assert.NoError(t, err)
|
||||
err = w.Flush()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// give it time to trigger
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
service.Shutdown()
|
||||
|
||||
assert.Equal(t, filePath, n.eventPath, "notifier didn't get an new file write event")
|
||||
}
|
14
watcher/notify.go
Normal file
14
watcher/notify.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package watcher
|
||||
|
||||
// Notification is the delegate methods from the Notifier
|
||||
type Notification interface {
|
||||
WatcherItemDidChange(string)
|
||||
WatcherDidError(error)
|
||||
}
|
||||
|
||||
// Notifier is the base interface for file watching
|
||||
type Notifier interface {
|
||||
Start(Notification)
|
||||
Add(string) error
|
||||
Shutdown()
|
||||
}
|
Reference in New Issue
Block a user