From 13aa560fda411e1e6abeb882edecfc0c4005cef7 Mon Sep 17 00:00:00 2001 From: Stuart Hickinbottom Date: Tue, 12 Mar 2024 14:22:43 +0000 Subject: [PATCH] Add PreValidate hook (#359) Fix #332. This adds a new "PreValidate" hook that is executed before checking the backup location. This allows, for example, mounting a remote source to make the directories of the location available. "PreValidate" is added as a new hook to avoid any breakage that might have been caused by changing the behaviour of the "before" hook. Documentataion updates included. --- README.md | 2 +- docs/pages/config.md | 2 ++ docs/pages/index.md | 2 +- docs/pages/location/hooks.md | 19 +++++++++++++------ internal/config.go | 9 +++++---- internal/location.go | 22 +++++++++++++++------- 6 files changed, 37 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 39ff481..e390bc2 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While - Backup locations to multiple backends - Snapshot policies and pruning - Fully encrypted -- Pre/After hooks +- Before/after backup hooks - Exclude pattern/files - Cron jobs for automatic backup - Backup & Restore docker volume diff --git a/docs/pages/config.md b/docs/pages/config.md index ce5aec5..9b7f604 100644 --- a/docs/pages/config.md +++ b/docs/pages/config.md @@ -56,6 +56,8 @@ version: 2 extras: hooks: &foo + prevalidate: + - echo "Wake up!" before: - echo "Hello" after: diff --git a/docs/pages/index.md b/docs/pages/index.md index ba9bd29..b3e24b5 100644 --- a/docs/pages/index.md +++ b/docs/pages/index.md @@ -13,7 +13,7 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While - Backup locations to multiple backends - Snapshot policies and pruning - Fully encrypted -- Pre/After hooks +- Before/after backup hooks - Exclude pattern/files - Cron jobs for automatic backup - Backup & Restore docker volumes diff --git a/docs/pages/location/hooks.md b/docs/pages/location/hooks.md index 6309526..a0b28be 100644 --- a/docs/pages/location/hooks.md +++ b/docs/pages/location/hooks.md @@ -6,23 +6,28 @@ They consist of a list of commands that will be executed in the same directory a The following hooks groups are supported, none are required: +- `prevalidate` - `before` - `after` - `failure` - `success` +The difference between `prevalidate` and `before` hooks are that `prevalidate` is run before checking the backup location is valid, including checking that the `from` directories exist. This can be useful, for example, to mount the source filesystem that contains the directories listed in `from`. + ```yml | .autorestic.yml locations: my-location: from: /data to: my-backend hooks: + prevalidate: + - echo "Checks" before: - echo "One" - echo "Two" - echo "Three" after: - - echo "Byte" + - echo "Bye" failure: - echo "Something went wrong" success: @@ -31,13 +36,15 @@ locations: ## Flowchart -1. `before` hook -2. Run backup -3. `after` hook -4. - `success` hook if no errors were found +1. `prevalidate` hook +2. Check backup location +3. `before` hook +4. Run backup +5. `after` hook +6. - `success` hook if no errors were found - `failure` hook if at least one error was encountered -If the `before` hook encounters errors the backup and `after` hooks will be skipped and only the `failed` hooks will run. +If either the `prevalidate` or `before` hook encounters errors then the backup and `after` hooks will be skipped and only the `failed` hooks will run. ## Environment variables diff --git a/internal/config.go b/internal/config.go index 46b7956..199e445 100644 --- a/internal/config.go +++ b/internal/config.go @@ -132,10 +132,11 @@ func (c *Config) Describe() { tmp = "" hooks := map[string][]string{ - "Before": l.Hooks.Before, - "After": l.Hooks.After, - "Failure": l.Hooks.Failure, - "Success": l.Hooks.Success, + "PreValidate": l.Hooks.PreValidate, + "Before": l.Hooks.Before, + "After": l.Hooks.After, + "Failure": l.Hooks.Failure, + "Success": l.Hooks.Success, } for hook, commands := range hooks { if len(commands) > 0 { diff --git a/internal/location.go b/internal/location.go index bf8deb5..a20efa7 100644 --- a/internal/location.go +++ b/internal/location.go @@ -33,11 +33,12 @@ const ( ) type Hooks struct { - Dir string `mapstructure:"dir"` - Before HookArray `mapstructure:"before,omitempty"` - After HookArray `mapstructure:"after,omitempty"` - Success HookArray `mapstructure:"success,omitempty"` - Failure HookArray `mapstructure:"failure,omitempty"` + Dir string `mapstructure:"dir"` + PreValidate HookArray `mapstructure:"prevalidate,omitempty"` + Before HookArray `mapstructure:"before,omitempty"` + After HookArray `mapstructure:"after,omitempty"` + Success HookArray `mapstructure:"success,omitempty"` + Failure HookArray `mapstructure:"failure,omitempty"` } type LocationCopy = map[string][]string @@ -184,12 +185,18 @@ func (l Location) Backup(cron bool, specificBackend string) []error { }, } + // Hooks before location validation + if err := l.ExecuteHooks(l.Hooks.PreValidate, options); err != nil { + errors = append(errors, err) + goto after + } + if err := l.validate(); err != nil { errors = append(errors, err) goto after } - // Hooks + // Hooks after location validation if err := l.ExecuteHooks(l.Hooks.Before, options); err != nil { errors = append(errors, err) goto after @@ -289,12 +296,13 @@ func (l Location) Backup(cron bool, specificBackend string) []error { } } - // After hooks + // After backup hooks if err := l.ExecuteHooks(l.Hooks.After, options); err != nil { errors = append(errors, err) } after: + // Success/failure hooks var commands []string var isSuccess = len(errors) == 0 if isSuccess {