package fileobserver import ( "fmt" "os" "time" "k8s.io/klog/v2" ) type Observer interface { Run(stopChan <-chan struct{}) HasSynced() bool AddReactor(reaction ReactorFn, startingFileContent map[string][]byte, files ...string) Observer } // ActionType define a type of action observed on the file type ActionType int const ( // FileModified means the file content was modified. FileModified ActionType = iota // FileCreated means the file was just created. FileCreated // FileDeleted means the file was deleted. FileDeleted ) func (t ActionType) name() string { switch t { case FileCreated: return "create" case FileDeleted: return "delete" case FileModified: return "modified" default: return "unknown" } } // String returns human readable form of action taken on a file. func (t ActionType) String(filename string) string { switch t { case FileCreated: return fmt.Sprintf("file %s was created", filename) case FileDeleted: return fmt.Sprintf("file %s was deleted", filename) case FileModified: return fmt.Sprintf("file %s was modified", filename) } return "" } // ReactorFn define a reaction function called when an observed file is modified. type ReactorFn func(file string, action ActionType) error // ExitOnChangeReactor provides reactor function that causes the process to exit when the change is detected. // DEPRECATED: Using this function cause process to exit immediately without proper shutdown (context close/etc.) // Use the TerminateOnChangeReactor() instead. var ExitOnChangeReactor = TerminateOnChangeReactor(func() { os.Exit(0) }) func TerminateOnChangeReactor(terminateFn func()) ReactorFn { return func(filename string, action ActionType) error { klog.Infof("Triggering shutdown because %s", action.String(filename)) terminateFn() return nil } } func NewObserver(interval time.Duration) (Observer, error) { return &pollingObserver{ interval: interval, reactors: map[string][]ReactorFn{}, files: map[string]fileHashAndState{}, }, nil }