github.com/argoproj/argo-cd/v2@v2.10.9/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/v2/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 func(watcher *fsnotify.Watcher) { 25 if err = watcher.Close(); err != nil { 26 log.Errorf("Error closing watcher: %v", err) 27 } 28 }(watcher) 29 30 done := make(chan bool) 31 go func() { 32 for { 33 select { 34 case event, ok := <-watcher.Events: 35 if !ok { 36 return 37 } 38 if event.Has(fsnotify.Create) || event.Has(fsnotify.Remove) { 39 // In case our watched path is re-created (i.e. during e2e tests), we need to watch again 40 // For more robustness, we retry re-creating the watcher up to maxRecreateRetries 41 if event.Name == sourcePath && event.Has(fsnotify.Remove) { 42 log.Warnf("Re-creating watcher on %s", sourcePath) 43 attempt := 0 44 for { 45 err = watcher.Add(sourcePath) 46 if err != nil { 47 log.Errorf("Error re-creating watcher on %s: %v", sourcePath, err) 48 if attempt < maxRecreateRetries { 49 attempt += 1 50 log.Infof("Retrying to re-create watcher, attempt %d of %d", attempt, maxRecreateRetries) 51 time.Sleep(1 * time.Second) 52 continue 53 } else { 54 log.Errorf("Maximum retries exceeded.") 55 close(done) 56 return 57 } 58 } 59 break 60 } 61 // Force sync because we probably missed an event 62 forceSync = true 63 } 64 if gpg.IsShortKeyID(path.Base(event.Name)) || forceSync { 65 log.Infof("Updating GPG keyring on filesystem event") 66 added, removed, err := gpg.SyncKeyRingFromDirectory(sourcePath) 67 if err != nil { 68 log.Errorf("Could not sync keyring: %s", err.Error()) 69 } else { 70 log.Infof("Result of sync operation: keys added: %d, keys removed: %d", len(added), len(removed)) 71 } 72 forceSync = false 73 } 74 } 75 case err, ok := <-watcher.Errors: 76 if !ok { 77 return 78 } 79 log.Errorf("%v", err) 80 } 81 } 82 }() 83 84 err = watcher.Add(sourcePath) 85 if err != nil { 86 return err 87 } 88 <-done 89 return fmt.Errorf("Abnormal termination of GPG watcher, refusing to continue.") 90 }