Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

watch directories #2589

Closed

Conversation

drewwells
Copy link
Contributor

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. Since by default, configmaps are mounted as
directories, I don't expect many people to find regressions when using this.

Signed-off-by: Drew Wells drew.wells00@gmail.com

@drewwells drewwells force-pushed the feature/fileEvents branch 2 times, most recently from 02a948c to c1c1b38 Compare July 30, 2020 22:12
@drewwells
Copy link
Contributor Author

If this looks like something that could be merged to the trunk, I will work on tests to verify expected behavior.

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. Since by default, configmaps are mounted as
directories, I don't expect many people to find regressions when using this.

Signed-off-by: Drew Wells <drew.wells00@gmail.com>
@drewwells drewwells force-pushed the feature/fileEvents branch from c1c1b38 to d996b48 Compare July 30, 2020 22:14
Copy link
Contributor

@patrick-east patrick-east left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

One aside for anyone who stumbles across this, generally speaking it isn't recommended to use the --watch feature for production usage for loading data/policies. Typically you would want to use the bundles: https://www.openpolicyagent.org/docs/latest/management/#bundles

The watch functionality is primarily intended for quick feedback/interactive policy authoring (eg. Start OPA and point to my local bundle source, edit files and either evaluate in the REPL or call some API to test the changes).

I left a few comments that we'll want to address, and then unit tests would be the last piece.

Comment on lines +629 to +633
// K8s likes to double symlink, resolve the symlink and fsnotify will resolve the next one
realPath, err := filepath.EvalSymlinks(path)
if err != nil {
return nil, err
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Couple things we should consider here. First is that OPA is by no means specific to K8s, so having behavior like this seems a little bit out of place. Second is that we are then relying on some implicit behavior on fsnotify to do a single resolve on our behalf.. which IMO isn't ideal.

If we move ahead with these changes we might as well go all the way and recursively resolve symlinks until we get to a "real" file/directory. AFAIK that should give the most consistent behavior across all the platforms OPA supports and runtimes (like k8s) where it gets deployed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The real file won't change either. K8s creates new files in different directories, and updates a symlink. The symlink event tends not to be registered so watching the directory is required. Watching a directory is hard to do with the implied notion that directories are bundles in the loader file.

Comment on lines +305 to +308
// Dirs converts all filepaths to directories to use in the file watcher.
// Some types of events will not register on the files themselves, so
// watch the directory to prevent this problem
func Dirs(paths []string) []string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't specific to the file watcher, right? If its just giving the set of parent directories for some list of paths we should update the comment to basically explain that.

unique := map[string]struct{}{}

for _, path := range paths {
// TODO: /dir/dir will register top level directory /dir
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the action for the TODO here? Should it not return the parent directory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you say watch a directory, which is supported today. The logic here will watch the parent directory instead. It may be fine, I'll convert this to a comment instead of a TODO.

Comment on lines +317 to +321
var u []string
for k := range unique {
u = append(u, k)
}
return u
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Do we need to filter out unique paths? IIUC fsnotify handles that for us if we Add watches for duplicates.

@patrick-east
Copy link
Contributor

@drewwells any update?

@patrick-east
Copy link
Contributor

Going to close this since there haven't been any updates. Please re-open if/when work continues on the changes.

@drewwells
Copy link
Contributor Author

I'll update this, my email notifications appear to be broken. I can't re-open the PR.

On the watch piece, we are using bundles with watch. We also plan to use this in production this way. Are there specific concerns with this or is it simply a less than ideal way to run OPA?

For context, we are attempting to use the k8s API to manage the bundles for OPA. Since OPA does not support talking directly to k8s API, we are mounting a k8s configmap to a volume. As k8s updates the configmap, the mounted path gets an update and OPA reloads the bundle. Another option is to support speaking k8s inside OPA. There's some benefits to both approaches, but OPA is easier to integrate with the file mounts. Thoughts?

@drewwells
Copy link
Contributor Author

@patrick-east can you open the PR? Tests are fixed.

@patrick-east
Copy link
Contributor

🤔 I don't have an option for it, github shows:
image

Some quick googling seems to indicate there are work-arounds like: https://gist.github.com/robertpainsi/2c42c15f1ce6dab03a0675348edd4e2c

@drewwells
Copy link
Contributor Author

My local git does not have the original sha, I'll open a new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants