-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwatcher.go
112 lines (95 loc) · 2.6 KB
/
watcher.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package main
import (
"github.com/fsnotify/fsnotify"
"github.com/go-logr/logr"
"os"
"path/filepath"
"sync"
)
func remove(slice []string, s int) []string {
return append(slice[:s], slice[s+1:]...)
}
type LabelWatcher struct {
fsWatcher *fsnotify.Watcher
watchedDirs []string
log logr.Logger
sync.RWMutex
}
func (l *LabelWatcher) Close() error {
return l.fsWatcher.Close()
}
func (l *LabelWatcher) Watch(done chan bool, refresh chan bool) {
l.log.Info("Monitoring filesystem for events...")
for {
select {
case evt := <-l.fsWatcher.Events:
var err error
if evt.Op&fsnotify.Create == fsnotify.Create {
info, _ := os.Stat(evt.Name)
if info.IsDir() {
l.log.Info("adding watcher", "dir", evt.Name)
l.Lock()
l.watchedDirs = append(l.watchedDirs, evt.Name)
l.fsWatcher.Add(evt.Name)
l.Unlock()
}
} else if evt.Op&fsnotify.Remove == fsnotify.Remove {
l.Lock()
for iter, dir := range l.watchedDirs {
if dir == evt.Name {
l.log.Info("removing watcher", "dir", evt.Name)
l.fsWatcher.Remove(evt.Name)
l.watchedDirs = remove(l.watchedDirs, iter)
}
}
l.Unlock()
}
// Reconstruct the list of possible labels. This must be done with the write lock held, as the manager
// goroutine may already be in the process of iterating the map when a filesystem update is triggered.
possibleLabelLock.Lock()
possibleLabelMap, err = buildPossibleLabelMap()
possibleLabelLock.Unlock()
if err != nil {
l.log.Error(err, "failed to update label map")
done <- true
} else {
// Label map has been updated, manually trigger node label reconciliation
refresh <- true
}
case err := <-l.fsWatcher.Errors:
l.log.Error(err, "received filesystem watcher error")
done <- true
}
}
}
func NewLabelWatcher(basePath string) (*LabelWatcher, error) {
watcherLog := log.WithName("watcher")
fsWatcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
watcher := &LabelWatcher{
log: watcherLog,
watchedDirs: make([]string, 0),
fsWatcher: fsWatcher,
}
if _, err := os.Stat(basePath); os.IsNotExist(err) {
log.Error(err, "invalid label directory specified")
return nil, err
}
err = filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
log.Info("Adding watcher", "dir", path)
watcher.Lock()
watcher.watchedDirs = append(watcher.watchedDirs, path)
watcher.fsWatcher.Add(path)
watcher.Unlock()
}
return nil
})
if err != nil {
log.Error(err, "unable to scan label dir")
return nil, err
}
return watcher, nil
}