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

file watcher to be used for configuration auto-reload feature #12301

Merged
merged 76 commits into from
Feb 21, 2022

Conversation

dhiaayachi
Copy link
Contributor

This PR add a file watcher that combine the use of https://github.com/fsnotify/fsnotify and a reconcile loop that id files by inode ID in linux and Creation Time in Windows to detect if file has been recreated and call a handler with the event accordingly.

For the time being this is not yet used in Consul but the the intent is to use it to automatically reload some of the configuration options when the file get recreated.

The 2 events that could trigger the handlers are:

  • Create: if a file watched is created or a file under a directory which is watched is created.
  • Remove: this will trigger an event only if the removed file is recreated (a file move use case)
  • In addition, a reconcile loop will run every 200 Milliseconds to go through all the watched files and check if any have a changed ID (Inode or creation time) and will trigger the event in this case.

Symlinks are not supported as fsnotify/fsnotify and the go filesystem packages are not consistent on how to treat symlinks and could get different behaviours (follow or not follow) depending on OS. If a symlink is added an error will be returned.

@github-actions github-actions bot added pr/dependencies PR specifically updates dependencies of project theme/config Relating to Consul Agent configuration, including reloading labels Feb 10, 2022
@dhiaayachi dhiaayachi added the pr/no-changelog PR does not need a corresponding .changelog entry label Feb 10, 2022
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 10, 2022 13:48 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 10, 2022 13:48 Inactive
Copy link
Contributor

@thisisnotashwin thisisnotashwin left a comment

Choose a reason for hiding this comment

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

Just a cleanup suggestion nit.

agent/config/file_watcher.go Outdated Show resolved Hide resolved
agent/config/file_watcher.go Outdated Show resolved Hide resolved
agent/config/file_watcher.go Show resolved Hide resolved
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 10, 2022 14:42 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 10, 2022 14:42 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 10, 2022 14:47 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 10, 2022 14:47 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 10, 2022 14:49 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 10, 2022 14:49 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 10, 2022 14:52 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 10, 2022 14:52 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 10, 2022 19:44 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 10, 2022 19:44 Inactive
Comment on lines +365 to +339
func randomStr(length int) string {
const charset = "abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var seededRand *rand.Rand = rand.New(
rand.NewSource(time.Now().UnixNano()))
b := make([]byte, length)
for i := range b {
b[i] = charset[seededRand.Intn(len(charset))]
}
return string(b)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added this helper to generate random strings, but if we already have something similar I could reuse.

@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 10, 2022 20:14 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 10, 2022 20:14 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 11, 2022 13:48 Inactive
}

// Stop the file watcher
// calling Stop multiple times is a noop
Copy link
Member

Choose a reason for hiding this comment

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

Also might be useful to say "Stop must only be called after Start" since the sequence of Stop, Start, Stop would leave the goroutine running.

require.NoError(t, assertEvent(file.Name(), w.EventsCh, defaultTimeout))
}

func TestEventWatcherRead(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

Is this testing that reading from a file (which may touch atime) doesn't notify you?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, this should not trigger any event but just in case another filesystem do something special.

_ = w.Stop()
}()

file.Chmod(0777)
Copy link
Member

Choose a reason for hiding this comment

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

This may error.

Comment on lines +126 to +128
recreated, err := os.Create(filepath)
require.NoError(t, err)
_, err = recreated.WriteString("config 2")
Copy link
Member

Choose a reason for hiding this comment

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

It's interesting you include this test setup since the order of operations here is actually the "unsafe" one you discuss elsewhere. In this case the filesystem sees:

  1. file name=X is erased
  2. file name=X is created and is empty
  3. file name=X is updated to not be empty

as 3 separate events, i guess here you're only going to see one of these. You could i guess end the test with an assert that times out to prove that you don't wake up more times than you expect.

Copy link
Member

@rboyer rboyer left a comment

Choose a reason for hiding this comment

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

LGTM with some non-blocking remaining comments.

@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 18, 2022 19:11 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 18, 2022 19:11 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 18, 2022 20:35 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 18, 2022 20:35 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 18, 2022 20:45 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 18, 2022 20:45 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 18, 2022 20:50 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 18, 2022 20:50 Inactive
Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com>
@vercel vercel bot temporarily deployed to Preview – consul February 18, 2022 20:52 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 18, 2022 20:52 Inactive
@vercel vercel bot temporarily deployed to Preview – consul February 21, 2022 16:20 Inactive
@vercel vercel bot temporarily deployed to Preview – consul-ui-staging February 21, 2022 16:20 Inactive
@dhiaayachi dhiaayachi merged commit cd9d8d4 into main Feb 21, 2022
@dhiaayachi dhiaayachi deleted the config-autoreload/file-watcher branch February 21, 2022 16:36
@hc-github-team-consul-core
Copy link
Contributor

🍒 If backport labels were added before merging, cherry-picking will start automatically.

To retroactively trigger a backport after merging, add backport labels and re-run https://circleci.com/gh/hashicorp/consul/590786.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr/dependencies PR specifically updates dependencies of project pr/no-changelog PR does not need a corresponding .changelog entry theme/config Relating to Consul Agent configuration, including reloading
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants