github.com/argoproj/argo-cd@v1.8.7/reposerver/gpgwatcher.go (about)

     1  package reposerver
     2  
     3  import (
     4  	"fmt"
     5  	"path"
     6  	"time"
     7  
     8  	"github.com/fsnotify/fsnotify"
     9  	log "github.com/sirupsen/logrus"
    10  
    11  	"github.com/argoproj/argo-cd/util/gpg"
    12  )
    13  
    14  const maxRecreateRetries = 5
    15  
    16  // StartGPGWatcher watches a given directory for creation and deletion of files and syncs the GPG keyring
    17  func StartGPGWatcher(sourcePath string) error {
    18  	log.Infof("Starting GPG sync watcher on directory '%s'", sourcePath)
    19  	forceSync := false
    20  	watcher, err := fsnotify.NewWatcher()
    21  	if err != nil {
    22  		return err
    23  	}
    24  	defer watcher.Close()
    25  
    26  	done := make(chan bool)
    27  	go func() {
    28  		for {
    29  			select {
    30  			case event, ok := <-watcher.Events:
    31  				if !ok {
    32  					return
    33  				}
    34  				if event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Remove == fsnotify.Remove {
    35  					// In case our watched path is re-created (i.e. during e2e tests), we need to watch again
    36  					// For more robustness, we retry re-creating the watcher up to maxRecreateRetries
    37  					if event.Name == sourcePath && event.Op&fsnotify.Remove == fsnotify.Remove {
    38  						log.Warnf("Re-creating watcher on %s", sourcePath)
    39  						attempt := 0
    40  						for {
    41  							err = watcher.Add(sourcePath)
    42  							if err != nil {
    43  								log.Errorf("Error re-creating watcher on %s: %v", sourcePath, err)
    44  								if attempt < maxRecreateRetries {
    45  									attempt += 1
    46  									log.Infof("Retrying to re-create watcher, attempt %d of %d", attempt, maxRecreateRetries)
    47  									time.Sleep(1 * time.Second)
    48  									continue
    49  								} else {
    50  									log.Errorf("Maximum retries exceeded.")
    51  									close(done)
    52  									return
    53  								}
    54  							}
    55  							break
    56  						}
    57  						// Force sync because we probably missed an event
    58  						forceSync = true
    59  					}
    60  					if gpg.IsShortKeyID(path.Base(event.Name)) || forceSync {
    61  						log.Infof("Updating GPG keyring on filesystem event")
    62  						added, removed, err := gpg.SyncKeyRingFromDirectory(sourcePath)
    63  						if err != nil {
    64  							log.Errorf("Could not sync keyring: %s", err.Error())
    65  						} else {
    66  							log.Infof("Result of sync operation: keys added: %d, keys removed: %d", len(added), len(removed))
    67  						}
    68  						forceSync = false
    69  					}
    70  				}
    71  			case err, ok := <-watcher.Errors:
    72  				if !ok {
    73  					return
    74  				}
    75  				log.Errorf("%v", err)
    76  			}
    77  		}
    78  	}()
    79  
    80  	err = watcher.Add(sourcePath)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	<-done
    85  	return fmt.Errorf("Abnormal termination of GPG watcher, refusing to continue.")
    86  }