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.
This commit is contained in:
Stuart Hickinbottom 2024-03-12 14:22:43 +00:00 committed by GitHub
parent bbb1c85cad
commit 13aa560fda
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 37 additions and 19 deletions

View File

@ -34,7 +34,7 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
- Backup locations to multiple backends - Backup locations to multiple backends
- Snapshot policies and pruning - Snapshot policies and pruning
- Fully encrypted - Fully encrypted
- Pre/After hooks - Before/after backup hooks
- Exclude pattern/files - Exclude pattern/files
- Cron jobs for automatic backup - Cron jobs for automatic backup
- Backup & Restore docker volume - Backup & Restore docker volume

View File

@ -56,6 +56,8 @@ version: 2
extras: extras:
hooks: &foo hooks: &foo
prevalidate:
- echo "Wake up!"
before: before:
- echo "Hello" - echo "Hello"
after: after:

View File

@ -13,7 +13,7 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
- Backup locations to multiple backends - Backup locations to multiple backends
- Snapshot policies and pruning - Snapshot policies and pruning
- Fully encrypted - Fully encrypted
- Pre/After hooks - Before/after backup hooks
- Exclude pattern/files - Exclude pattern/files
- Cron jobs for automatic backup - Cron jobs for automatic backup
- Backup & Restore docker volumes - Backup & Restore docker volumes

View File

@ -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: The following hooks groups are supported, none are required:
- `prevalidate`
- `before` - `before`
- `after` - `after`
- `failure` - `failure`
- `success` - `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 ```yml | .autorestic.yml
locations: locations:
my-location: my-location:
from: /data from: /data
to: my-backend to: my-backend
hooks: hooks:
prevalidate:
- echo "Checks"
before: before:
- echo "One" - echo "One"
- echo "Two" - echo "Two"
- echo "Three" - echo "Three"
after: after:
- echo "Byte" - echo "Bye"
failure: failure:
- echo "Something went wrong" - echo "Something went wrong"
success: success:
@ -31,13 +36,15 @@ locations:
## Flowchart ## Flowchart
1. `before` hook 1. `prevalidate` hook
2. Run backup 2. Check backup location
3. `after` hook 3. `before` hook
4. - `success` hook if no errors were found 4. Run backup
5. `after` hook
6. - `success` hook if no errors were found
- `failure` hook if at least one error was encountered - `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 ## Environment variables

View File

@ -132,10 +132,11 @@ func (c *Config) Describe() {
tmp = "" tmp = ""
hooks := map[string][]string{ hooks := map[string][]string{
"Before": l.Hooks.Before, "PreValidate": l.Hooks.PreValidate,
"After": l.Hooks.After, "Before": l.Hooks.Before,
"Failure": l.Hooks.Failure, "After": l.Hooks.After,
"Success": l.Hooks.Success, "Failure": l.Hooks.Failure,
"Success": l.Hooks.Success,
} }
for hook, commands := range hooks { for hook, commands := range hooks {
if len(commands) > 0 { if len(commands) > 0 {

View File

@ -33,11 +33,12 @@ const (
) )
type Hooks struct { type Hooks struct {
Dir string `mapstructure:"dir"` Dir string `mapstructure:"dir"`
Before HookArray `mapstructure:"before,omitempty"` PreValidate HookArray `mapstructure:"prevalidate,omitempty"`
After HookArray `mapstructure:"after,omitempty"` Before HookArray `mapstructure:"before,omitempty"`
Success HookArray `mapstructure:"success,omitempty"` After HookArray `mapstructure:"after,omitempty"`
Failure HookArray `mapstructure:"failure,omitempty"` Success HookArray `mapstructure:"success,omitempty"`
Failure HookArray `mapstructure:"failure,omitempty"`
} }
type LocationCopy = map[string][]string 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 { if err := l.validate(); err != nil {
errors = append(errors, err) errors = append(errors, err)
goto after goto after
} }
// Hooks // Hooks after location validation
if err := l.ExecuteHooks(l.Hooks.Before, options); err != nil { if err := l.ExecuteHooks(l.Hooks.Before, options); err != nil {
errors = append(errors, err) errors = append(errors, err)
goto after 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 { if err := l.ExecuteHooks(l.Hooks.After, options); err != nil {
errors = append(errors, err) errors = append(errors, err)
} }
after: after:
// Success/failure hooks
var commands []string var commands []string
var isSuccess = len(errors) == 0 var isSuccess = len(errors) == 0
if isSuccess { if isSuccess {