Use int comparison for checking hooks

This commit is contained in:
Frederik Ring 2021-12-17 20:45:15 +01:00
parent 8bad0656b3
commit 88c90a206c
2 changed files with 28 additions and 24 deletions

View File

@ -249,10 +249,11 @@ You can populate below template according to your requirements and use it as you
# NOTIFICATION_URLS=smtp://username:password@host:587/?fromAddress=sender@example.com&toAddresses=recipient@example.com # NOTIFICATION_URLS=smtp://username:password@host:587/?fromAddress=sender@example.com&toAddresses=recipient@example.com
# By default, notifications will only be sent out when a backup run fails. # By default, notifications will only be sent out when a backup run fails
# To receive notifications for every run, set `NOTIFICATION_LEVEL` to `always` # (i.e. `error`). To receive notifications for every run, set
# `NOTIFICATION_LEVEL` to `info`
# NOTIFICATION_LEVEL="always" # NOTIFICATION_LEVEL="info"
########### EMAIL NOTIFICATIONS ########### EMAIL NOTIFICATIONS

View File

@ -44,7 +44,7 @@ func main() {
defer func() { defer func() {
if pArg := recover(); pArg != nil { if pArg := recover(); pArg != nil {
if err, ok := pArg.(error); ok { if err, ok := pArg.(error); ok {
if hookErr := s.runHooks(err, hookLevelCleanup, hookLevelFailure, hookLevelAlways); hookErr != nil { if hookErr := s.runHooks(err, hookLevelError); hookErr != nil {
s.logger.Errorf("An error occurred calling the registered hooks: %s", hookErr) s.logger.Errorf("An error occurred calling the registered hooks: %s", hookErr)
} }
os.Exit(1) os.Exit(1)
@ -52,7 +52,7 @@ func main() {
panic(pArg) panic(pArg)
} }
if err := s.runHooks(nil, hookLevelCleanup, hookLevelAlways); err != nil { if err := s.runHooks(nil, hookLevelInfo); err != nil {
s.logger.Errorf( s.logger.Errorf(
"Backup procedure ran successfully, but an error ocurred calling the registered hooks: %v", "Backup procedure ran successfully, but an error ocurred calling the registered hooks: %v",
err, err,
@ -115,7 +115,7 @@ type config struct {
AwsIamRoleEndpoint string `split_words:"true"` AwsIamRoleEndpoint string `split_words:"true"`
GpgPassphrase string `split_words:"true"` GpgPassphrase string `split_words:"true"`
NotificationURLs []string `envconfig:"NOTIFICATION_URLS"` NotificationURLs []string `envconfig:"NOTIFICATION_URLS"`
NotificationLevel string `split_words:"true" default:"failure"` NotificationLevel string `split_words:"true" default:"error"`
EmailNotificationRecipient string `split_words:"true"` EmailNotificationRecipient string `split_words:"true"`
EmailNotificationSender string `split_words:"true" default:"noreply@nohost"` EmailNotificationSender string `split_words:"true" default:"noreply@nohost"`
EmailSMTPHost string `envconfig:"EMAIL_SMTP_HOST"` EmailSMTPHost string `envconfig:"EMAIL_SMTP_HOST"`
@ -217,9 +217,9 @@ func newScript() (*script, error) {
) )
} }
notificationLevel := hookLevelFailure notificationLevel, ok := notificationLevels[s.c.NotificationLevel]
if s.c.NotificationLevel == "always" { if !ok {
notificationLevel = hookLevelAlways return nil, fmt.Errorf("newScript: unknown NOTIFICATION_LEVEL %s", s.c.NotificationLevel)
} }
s.registerHook(notificationLevel, s.sendNotification) s.registerHook(notificationLevel, s.sendNotification)
@ -392,7 +392,7 @@ func (s *script) takeBackup() error {
if s.c.BackupFromSnapshot { if s.c.BackupFromSnapshot {
backupSources = filepath.Join("/tmp", s.c.BackupSources) backupSources = filepath.Join("/tmp", s.c.BackupSources)
// copy before compressing guard against a situation where backup folder's content are still growing. // copy before compressing guard against a situation where backup folder's content are still growing.
s.registerHook(hookLevelCleanup, func(error) error { s.registerHook(hookLevelPlumbing, func(error) error {
if err := remove(backupSources); err != nil { if err := remove(backupSources); err != nil {
return fmt.Errorf("takeBackup: error removing snapshot: %w", err) return fmt.Errorf("takeBackup: error removing snapshot: %w", err)
} }
@ -409,7 +409,7 @@ func (s *script) takeBackup() error {
} }
tarFile := s.file tarFile := s.file
s.registerHook(hookLevelCleanup, func(error) error { s.registerHook(hookLevelPlumbing, func(error) error {
if err := remove(tarFile); err != nil { if err := remove(tarFile); err != nil {
return fmt.Errorf("takeBackup: error removing tar file: %w", err) return fmt.Errorf("takeBackup: error removing tar file: %w", err)
} }
@ -433,7 +433,7 @@ func (s *script) encryptBackup() error {
} }
gpgFile := fmt.Sprintf("%s.gpg", s.file) gpgFile := fmt.Sprintf("%s.gpg", s.file)
s.registerHook(hookLevelCleanup, func(error) error { s.registerHook(hookLevelPlumbing, func(error) error {
if err := remove(gpgFile); err != nil { if err := remove(gpgFile); err != nil {
return fmt.Errorf("encryptBackup: error removing gpg file: %w", err) return fmt.Errorf("encryptBackup: error removing gpg file: %w", err)
} }
@ -660,16 +660,14 @@ func (s *script) pruneOldBackups() error {
// runHooks runs all hooks that have been registered using the // runHooks runs all hooks that have been registered using the
// given levels in the defined ordering. In case executing a hook returns an // given levels in the defined ordering. In case executing a hook returns an
// error, the following hooks will still be run before the function returns. // error, the following hooks will still be run before the function returns.
func (s *script) runHooks(err error, levels ...hookLevel) error { func (s *script) runHooks(err error, level hookLevel) error {
var actionErrors []error var actionErrors []error
for _, level := range levels { for _, hook := range s.hooks {
for _, hook := range s.hooks { if hook.level > level {
if hook.level != level { continue
continue }
} if actionErr := hook.action(err); actionErr != nil {
if actionErr := hook.action(err); actionErr != nil { actionErrors = append(actionErrors, fmt.Errorf("runHooks: error running hook: %w", actionErr))
actionErrors = append(actionErrors, fmt.Errorf("runHooks: error running hook: %w", actionErr))
}
} }
} }
if len(actionErrors) != 0 { if len(actionErrors) != 0 {
@ -787,7 +785,12 @@ type hook struct {
type hookLevel int type hookLevel int
const ( const (
hookLevelFailure hookLevel = iota hookLevelPlumbing hookLevel = iota
hookLevelAlways hookLevelInfo
hookLevelCleanup hookLevelError
) )
var notificationLevels = map[string]hookLevel{
"info": hookLevelInfo,
"error": hookLevelError,
}