-
Notifications
You must be signed in to change notification settings - Fork 126
/
watcher.go
108 lines (86 loc) · 2.72 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
package kubeconfig
import (
"os"
"path/filepath"
"time"
"github.com/fsnotify/fsnotify"
"github.com/headlamp-k8s/headlamp/backend/pkg/logger"
"k8s.io/utils/strings/slices"
)
const watchInterval = 10 * time.Second
// LoadAndWatchFiles loads kubeconfig files and watches them for changes.
func LoadAndWatchFiles(kubeConfigStore ContextStore, paths string, source int) {
// create ticker
ticker := time.NewTicker(watchInterval)
// create watcher
watcher, err := fsnotify.NewWatcher()
if err != nil {
logger.Log(logger.LevelError, nil, err, "creating watcher")
return
}
defer watcher.Close()
kubeConfigPaths := splitKubeConfigPath(paths)
// add files to watcher
addFilesToWatcher(watcher, kubeConfigPaths)
for {
select {
case <-ticker.C:
if len(watcher.WatchList()) != len(kubeConfigPaths) {
logger.Log(logger.LevelInfo, nil, nil, "watcher: re-adding missing files")
addFilesToWatcher(watcher, kubeConfigPaths)
err := LoadAndStoreKubeConfigs(kubeConfigStore, paths, source)
if err != nil {
logger.Log(logger.LevelError, nil, err, "watcher: error loading kubeconfig files")
}
}
case event := <-watcher.Events:
triggers := []fsnotify.Op{fsnotify.Create, fsnotify.Write, fsnotify.Remove, fsnotify.Rename}
for _, trigger := range triggers {
trigger := trigger
if event.Op.Has(trigger) {
logger.Log(logger.LevelInfo, map[string]string{"event": event.Name},
nil, "watcher: kubeconfig file changed, reloading contexts")
err := LoadAndStoreKubeConfigs(kubeConfigStore, paths, source)
if err != nil {
logger.Log(logger.LevelError, nil, err, "watcher: error loading kubeconfig files")
}
}
}
case err := <-watcher.Errors:
logger.Log(logger.LevelError, nil, err, "watcher: error watching kubeconfig files")
}
}
}
func addFilesToWatcher(watcher *fsnotify.Watcher, paths []string) {
for _, path := range paths {
path := path
// if path is relative, make it absolute
if !filepath.IsAbs(path) {
absPath, err := filepath.Abs(path)
if err != nil {
logger.Log(logger.LevelError, map[string]string{"path": path},
err, "getting absolute path")
continue
}
path = absPath
}
// check if path exists
if _, err := os.Stat(path); os.IsNotExist(err) {
logger.Log(logger.LevelError, map[string]string{"path": path},
err, "Path does not exist")
continue
}
// check if path is already being watched
// if it is, continue
filesBeingWatched := watcher.WatchList()
if slices.Contains(filesBeingWatched, path) {
continue
}
// if it isn't, add it to the watcher
err := watcher.Add(path)
if err != nil {
logger.Log(logger.LevelError, map[string]string{"path": path},
err, "adding path to watcher")
}
}
}