diff --git a/cmd/backup/run_script.go b/cmd/backup/run_script.go index aee9d2c7..c65862d3 100644 --- a/cmd/backup/run_script.go +++ b/cmd/backup/run_script.go @@ -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 @@ -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 { diff --git a/cmd/backup/script.go b/cmd/backup/script.go index 186f0c04..d6b76b9d 100644 --- a/cmd/backup/script.go +++ b/cmd/backup/script.go @@ -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) @@ -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 }