Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions integration/reload.bats
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,40 @@ grep_test_file() {
kill -s TERM "$PID"
wait
}

@test "if inotify is enabled it handles RENAME events (vim-style atomic writes)" {
echo '* * * * * * * echo a > "$TEST_FILE"' > "$CRONTAB_FILE"

"${BATS_TEST_DIRNAME}/../supercronic" -inotify "$CRONTAB_FILE" 3>&- &
PID="$!"

wait_for grep_test_file a

# Simulate vim-style atomic write: create temp file, write to it, rename over original
TEMP_FILE="${CRONTAB_FILE}.tmp"
echo '* * * * * * * echo b > "$TEST_FILE"' > "$TEMP_FILE"
mv "$TEMP_FILE" "$CRONTAB_FILE"

wait_for grep_test_file b

kill -s TERM "$PID"
wait
}

@test "if inotify is enabled it handles CREATE events (file recreation)" {
echo '* * * * * * * echo a > "$TEST_FILE"' > "$CRONTAB_FILE"

"${BATS_TEST_DIRNAME}/../supercronic" -inotify "$CRONTAB_FILE" 3>&- &
PID="$!"

wait_for grep_test_file a

# Simulate Create event: remove file, then create new one at same path
rm "$CRONTAB_FILE"
echo '* * * * * * * echo b > "$TEST_FILE"' > "$CRONTAB_FILE"

wait_for grep_test_file b

kill -s TERM "$PID"
wait
}
31 changes: 23 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,19 +202,34 @@ func main() {
}
logrus.Debugf("event: %v, watch-list: %v", event, watcher.WatchList())

switch event.Op {
case event.Op & fsnotify.Write:
logrus.Debug("watched file changed")
// Handle any file modification event (Write, Create, Remove, Rename)
// Many editors use atomic writes that generate Rename or Create events
if event.Op&fsnotify.Write != 0 {
logrus.Debug("watched file changed (write)")
termChan <- syscall.SIGUSR2

// workaround for k8s configmap and secret mounts
case event.Op & fsnotify.Remove:
logrus.Debug("watched file changed")
// workaround for k8s configmap and secret mounts
} else if event.Op&fsnotify.Create != 0 {
logrus.Debug("watched file changed (create)")
termChan <- syscall.SIGUSR2
} else if event.Op&fsnotify.Rename != 0 {
logrus.Debug("watched file changed (rename)")
// Re-add watch after rename (file might have been replaced)
if err := watcher.Add(crontabFileName); err != nil {
logrus.Errorf("failed to re-add watch after rename: %s", err)
logrus.Fatal(err)
return
} else {
termChan <- syscall.SIGUSR2
}
} else if event.Op&fsnotify.Remove != 0 {
// workaround for k8s configmap and secret mounts
logrus.Debug("watched file changed (remove)")
if err := watcher.Add(crontabFileName); err != nil {
logrus.Errorf("failed to re-add watch: %s", err)
// Don't return/fatal here - just log and continue
} else {
termChan <- syscall.SIGUSR2
}
termChan <- syscall.SIGUSR2
}

case err, ok := <-watcher.Errors:
Expand Down