inspect symlinks to auto-reload k8s secrets
This commit is contained in:
parent
87aa96b468
commit
d280a344c4
2 changed files with 94 additions and 4 deletions
|
@ -18,7 +18,9 @@ package watch
|
|||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
|
@ -60,15 +62,31 @@ func (f *OSFileWatcher) watch() error {
|
|||
}
|
||||
f.watcher = watcher
|
||||
|
||||
realFile, err := filepath.EvalSymlinks(f.file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dir, file := path.Split(f.file)
|
||||
go func(file string) {
|
||||
for {
|
||||
select {
|
||||
case event := <-watcher.Events:
|
||||
if (event.Op&fsnotify.Write == fsnotify.Write ||
|
||||
event.Op&fsnotify.Create == fsnotify.Create) &&
|
||||
strings.HasSuffix(event.Name, file) {
|
||||
f.onEvent()
|
||||
if event.Op&fsnotify.Create == fsnotify.Create ||
|
||||
event.Op&fsnotify.Write == fsnotify.Write {
|
||||
if finfo, err := os.Lstat(event.Name); err != nil {
|
||||
log.Printf("can not lstat file: %v\n", err)
|
||||
} else if finfo.Mode()&os.ModeSymlink != 0 {
|
||||
if currentRealFile, err := filepath.EvalSymlinks(f.file); err == nil &&
|
||||
currentRealFile != realFile {
|
||||
f.onEvent()
|
||||
realFile = currentRealFile
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(event.Name, file) {
|
||||
f.onEvent()
|
||||
}
|
||||
}
|
||||
case err := <-watcher.Errors:
|
||||
if err != nil {
|
||||
|
|
|
@ -19,6 +19,8 @@ package watch
|
|||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -67,3 +69,73 @@ func TestFileWatcher(t *testing.T) {
|
|||
t.Fatalf("expected an event shortly after writing a file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileWatcherWithNestedSymlink(t *testing.T) {
|
||||
target1, err := ioutil.TempFile("", "t1")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
defer target1.Close()
|
||||
defer os.Remove(target1.Name())
|
||||
dir := path.Dir(target1.Name())
|
||||
|
||||
innerLink := path.Join(dir, "innerLink")
|
||||
if err = os.Symlink(target1.Name(), innerLink); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
defer os.Remove(innerLink)
|
||||
mainLink := path.Join(dir, "mainLink")
|
||||
if err = os.Symlink(innerLink, mainLink); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
defer os.Remove(mainLink)
|
||||
|
||||
targetName, err := filepath.EvalSymlinks(mainLink)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if targetName != target1.Name() {
|
||||
t.Fatalf("expected symlink to point to %v, not %v", target1.Name(), targetName)
|
||||
}
|
||||
|
||||
count := 0
|
||||
events := make(chan bool, 10)
|
||||
fw, err := NewFileWatcher(mainLink, func() {
|
||||
count++
|
||||
if count != 1 {
|
||||
t.Fatalf("expected 1 but returned %v", count)
|
||||
}
|
||||
if targetName, err = filepath.EvalSymlinks(mainLink); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
events <- true
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
target2, err := ioutil.TempFile("", "t2")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
defer target2.Close()
|
||||
defer os.Remove(target2.Name())
|
||||
|
||||
if err = os.Remove(innerLink); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if err = os.Symlink(target2.Name(), innerLink); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
timeoutChan := prepareTimeout()
|
||||
select {
|
||||
case <-events:
|
||||
case <-timeoutChan:
|
||||
t.Fatalf("expected an event shortly after creating a file and relinking")
|
||||
}
|
||||
if targetName != target2.Name() {
|
||||
t.Fatalf("expected symlink to point to %v, not %v", target2.Name(), targetName)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue