Skip to content

Commit

Permalink
file watching only watches parent directory
Browse files Browse the repository at this point in the history
Watching files only works in situations where standard files are in
use. In k8s, configmaps are mounted via a set of symlinks. In those
situations, you will only get file events when watching the directory
containing the symlink.

Fixes open-policy-agent#2588

Signed-off-by: Drew Wells <drew.wells00@gmail.com>
  • Loading branch information
drewwells committed Aug 28, 2020
1 parent dd78d44 commit a1e06ad
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
20 changes: 20 additions & 0 deletions loader/loader.go
Expand Up @@ -11,6 +11,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"

"github.com/ghodss/yaml"
Expand Down Expand Up @@ -302,6 +303,25 @@ func Paths(path string, recurse bool) (paths []string, err error) {
return paths, err
}

// Dirs resolves filepaths to directories. It will return a list of unique
// directories.
func Dirs(paths []string) []string {
unique := map[string]struct{}{}

for _, path := range paths {
// TODO: /dir/dir will register top level directory /dir
dir := filepath.Dir(path)
unique[dir] = struct{}{}
}

var u []string
for k := range unique {
u = append(u, k)
}
sort.Strings(u)
return u
}

// SplitPrefix returns a tuple specifying the document prefix and the file
// path.
func SplitPrefix(path string) ([]string, string) {
Expand Down
12 changes: 12 additions & 0 deletions loader/loader_test.go
Expand Up @@ -717,3 +717,15 @@ func mustListPaths(path string, recurse bool) (paths []string) {
}
return paths
}

func TestDirs(t *testing.T) {
paths := []string{
"/foo/bar.json", "/foo/bar/baz.json", "/foo.json",
}

e := []string{"/", "/foo", "/foo/bar"}
sorted := Dirs(paths)
if !reflect.DeepEqual(sorted, e) {
t.Errorf("got: %q wanted: %q", sorted, e)
}
}
7 changes: 6 additions & 1 deletion runtime/runtime.go
Expand Up @@ -528,9 +528,13 @@ func (rt *Runtime) readWatcher(ctx context.Context, watcher *fsnotify.Watcher, p
for {
select {
case evt := <-watcher.Events:

removalMask := (fsnotify.Remove | fsnotify.Rename)
mask := (fsnotify.Create | fsnotify.Write | removalMask)
if (evt.Op & mask) != 0 {
logrus.WithFields(logrus.Fields{
"event": evt.String(),
}).Debugf("registered file event")
t0 := time.Now()
removed := ""
if (evt.Op & removalMask) != 0 {
Expand Down Expand Up @@ -656,6 +660,7 @@ func getWatcher(rootPaths []string) (*fsnotify.Watcher, error) {
}

for _, path := range watchPaths {
logrus.WithField("path", path).Debug("watching path")
if err := watcher.Add(path); err != nil {
return nil, err
}
Expand All @@ -675,7 +680,7 @@ func getWatchPaths(rootPaths []string) ([]string, error) {
return nil, err
}

paths = append(paths, result...)
paths = append(paths, loader.Dirs(result)...)
}

return paths, nil
Expand Down
7 changes: 4 additions & 3 deletions runtime/runtime_test.go
Expand Up @@ -13,6 +13,7 @@ import (
"net/http/httptest"
"os"
"path"
"path/filepath"
"reflect"
"strings"
"testing"
Expand All @@ -36,7 +37,7 @@ func TestWatchPaths(t *testing.T) {
}

expected := []string{
"/foo", "/foo/bar", "/foo/bar/baz.json",
".", "/foo", "/foo/bar",
}

test.WithTempFS(fs, func(rootDir string) {
Expand All @@ -46,10 +47,10 @@ func TestWatchPaths(t *testing.T) {
}
result := []string{}
for _, path := range paths {
result = append(result, strings.TrimPrefix(path, rootDir))
result = append(result, filepath.Clean(strings.TrimPrefix(path, rootDir)))
}
if !reflect.DeepEqual(expected, result) {
t.Fatalf("Expected %v but got: %v", expected, result)
t.Fatalf("Expected %q but got: %q", expected, result)
}
})
}
Expand Down

0 comments on commit a1e06ad

Please sign in to comment.