Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notification hooks do not run on locking failure #385

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 41 additions & 32 deletions cmd/backup/run_script.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,36 @@ func runScript(c *Config) (err error) {

s := newScript(c)

unlock, lockErr := s.lock("/var/lock/dockervolumebackup.lock")
if lockErr != nil {
err = errwrap.Wrap(lockErr, "error acquiring file lock")
return
}
defer func() {
if derr := unlock(); derr != nil {
err = errors.Join(err, errwrap.Wrap(derr, "error releasing file lock"))
}
}()
return func() (err error) {
scriptErr := func() (err error) {
unset, err := s.c.applyEnv()
if err != nil {
err = errwrap.Wrap(err, "error applying env")
return
}
defer func() {
if derr := unset(); derr != nil {
err = errors.Join(err, errwrap.Wrap(derr, "error unsetting environment variables"))
}
}()

unset, err := s.c.applyEnv()
if err != nil {
return errwrap.Wrap(err, "error applying env")
}
defer func() {
if derr := unset(); derr != nil {
err = errors.Join(err, errwrap.Wrap(derr, "error unsetting environment variables"))
}
}()
if initErr := s.init(); initErr != nil {
err = errwrap.Wrap(initErr, "error instantiating script")
return
}

if initErr := s.init(); initErr != nil {
err = errwrap.Wrap(initErr, "error instantiating script")
return
}
unlock, lockErr := s.lock("/var/lock/dockervolumebackup.lock")
if lockErr != nil {
err = errwrap.Wrap(lockErr, "error acquiring file lock")
return
}

defer func() {
if derr := unlock(); derr != nil {
err = errors.Join(err, errwrap.Wrap(derr, "error releasing file lock"))
}
}()

return func() (err error) {
scriptErr := func() error {
if err := s.withLabeledCommands(lifecyclePhaseArchive, func() (err error) {
restartContainersAndServices, err := s.stopContainersAndServices()
// The mechanism for restarting containers is not using hooks as it
Expand All @@ -75,16 +77,23 @@ func runScript(c *Config) (err error) {
return err
}

if err := s.withLabeledCommands(lifecyclePhaseProcess, s.encryptArchive)(); err != nil {
return err
err = s.withLabeledCommands(lifecyclePhaseProcess, s.encryptArchive)()
if err != nil {
err = errwrap.Wrap(err, "error encrypting archive")
return
}
if err := s.withLabeledCommands(lifecyclePhaseCopy, s.copyArchive)(); err != nil {
return err
err = s.withLabeledCommands(lifecyclePhaseCopy, s.copyArchive)()
if err != nil {
err = errwrap.Wrap(err, "error copying archive")
return
}
if err := s.withLabeledCommands(lifecyclePhasePrune, s.pruneBackups)(); err != nil {
return err
err = s.withLabeledCommands(lifecyclePhasePrune, s.pruneBackups)()
if err != nil {
err = errwrap.Wrap(err, "error pruning backups")
return
}
return nil

return
}()

if hookErr := s.runHooks(scriptErr); hookErr != nil {
Expand Down
88 changes: 44 additions & 44 deletions cmd/backup/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,50 @@ func (s *script) init() error {
return nil
})

hookLevel, ok := hookLevels[s.c.NotificationLevel]
if !ok {
return errwrap.Wrap(nil, fmt.Sprintf("unknown NOTIFICATION_LEVEL %s", s.c.NotificationLevel))
}
s.hookLevel = hookLevel

if len(s.c.NotificationURLs) > 0 {
sender, senderErr := shoutrrr.CreateSender(s.c.NotificationURLs...)
if senderErr != nil {
return errwrap.Wrap(senderErr, "error creating sender")
}
s.sender = sender

tmpl := template.New("")
tmpl.Funcs(templateHelpers)
tmpl, err := tmpl.Parse(defaultNotifications)
if err != nil {
return errwrap.Wrap(err, "unable to parse default notifications templates")
}

if fi, err := os.Stat("/etc/dockervolumebackup/notifications.d"); err == nil && fi.IsDir() {
tmpl, err = tmpl.ParseGlob("/etc/dockervolumebackup/notifications.d/*.*")
if err != nil {
return errwrap.Wrap(err, "unable to parse user defined notifications templates")
}
}
s.template = tmpl

// To prevent duplicate notifications, ensure the regsistered callbacks
// run mutually exclusive.
s.registerHook(hookLevelError, func(err error) error {
if err == nil {
return nil
}
return s.notifyFailure(err)
})
s.registerHook(hookLevelInfo, func(err error) error {
if err != nil {
return nil
}
return s.notifySuccess()
})
}

s.file = path.Join("/tmp", s.c.BackupFilename)

tmplFileName, tErr := template.New("extension").Parse(s.file)
Expand Down Expand Up @@ -238,49 +282,5 @@ func (s *script) init() error {
)
}

hookLevel, ok := hookLevels[s.c.NotificationLevel]
if !ok {
return errwrap.Wrap(nil, fmt.Sprintf("unknown NOTIFICATION_LEVEL %s", s.c.NotificationLevel))
}
s.hookLevel = hookLevel

if len(s.c.NotificationURLs) > 0 {
sender, senderErr := shoutrrr.CreateSender(s.c.NotificationURLs...)
if senderErr != nil {
return errwrap.Wrap(senderErr, "error creating sender")
}
s.sender = sender

tmpl := template.New("")
tmpl.Funcs(templateHelpers)
tmpl, err = tmpl.Parse(defaultNotifications)
if err != nil {
return errwrap.Wrap(err, "unable to parse default notifications templates")
}

if fi, err := os.Stat("/etc/dockervolumebackup/notifications.d"); err == nil && fi.IsDir() {
tmpl, err = tmpl.ParseGlob("/etc/dockervolumebackup/notifications.d/*.*")
if err != nil {
return errwrap.Wrap(err, "unable to parse user defined notifications templates")
}
}
s.template = tmpl

// To prevent duplicate notifications, ensure the regsistered callbacks
// run mutually exclusive.
s.registerHook(hookLevelError, func(err error) error {
if err == nil {
return nil
}
return s.notifyFailure(err)
})
s.registerHook(hookLevelInfo, func(err error) error {
if err != nil {
return nil
}
return s.notifySuccess()
})
}

return nil
}
Loading