github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/hooks/monitor.go (about)

     1  package hooks
     2  
     3  import (
     4  	"context"
     5  
     6  	current "github.com/containers/libpod/pkg/hooks/1.0.0"
     7  	"github.com/fsnotify/fsnotify"
     8  	"github.com/sirupsen/logrus"
     9  )
    10  
    11  // Monitor dynamically monitors hook directories for additions,
    12  // updates, and removals.
    13  //
    14  // This function writes two empty structs to the sync channel: the
    15  // first is written after the watchers are established and the second
    16  // when this function exits.  The expected usage is:
    17  //
    18  //   ctx, cancel := context.WithCancel(context.Background())
    19  //   sync := make(chan error, 2)
    20  //   go m.Monitor(ctx, sync)
    21  //   err := <-sync // block until writers are established
    22  //   if err != nil {
    23  //     return err // failed to establish watchers
    24  //   }
    25  //   // do stuff
    26  //   cancel()
    27  //   err = <-sync // block until monitor finishes
    28  func (m *Manager) Monitor(ctx context.Context, sync chan<- error) {
    29  	watcher, err := fsnotify.NewWatcher()
    30  	if err != nil {
    31  		sync <- err
    32  		return
    33  	}
    34  	defer watcher.Close()
    35  
    36  	for _, dir := range m.directories {
    37  		err = watcher.Add(dir)
    38  		if err != nil {
    39  			logrus.Errorf("failed to watch %q for hooks", dir)
    40  			sync <- err
    41  			return
    42  		}
    43  		logrus.Debugf("monitoring %q for hooks", dir)
    44  	}
    45  
    46  	sync <- nil
    47  
    48  	for {
    49  		select {
    50  		case event := <-watcher.Events:
    51  			m.hooks = make(map[string]*current.Hook)
    52  			for _, dir := range m.directories {
    53  				err = ReadDir(dir, m.extensionStages, m.hooks)
    54  				if err != nil {
    55  					logrus.Errorf("failed loading hooks for %s: %v", event.Name, err)
    56  				}
    57  			}
    58  		case <-ctx.Done():
    59  			err = ctx.Err()
    60  			logrus.Debugf("hook monitoring canceled: %v", err)
    61  			sync <- err
    62  			close(sync)
    63  			return
    64  		}
    65  	}
    66  }