Skip to content

Commit a41bea0

Browse files
author
Romain de Laage
committed
Add restore hooks feature
1 parent 2b9dc9f commit a41bea0

File tree

2 files changed

+74
-21
lines changed

2 files changed

+74
-21
lines changed

cmd/restore.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/cupcakearmy/autorestic/internal"
7+
"github.com/cupcakearmy/autorestic/internal/colors"
78
"github.com/cupcakearmy/autorestic/internal/lock"
89
"github.com/spf13/cobra"
910
)
@@ -42,8 +43,13 @@ var restoreCmd = &cobra.Command{
4243
}
4344
}
4445

45-
err = l.Restore(target, from, force, snapshot, optional)
46-
CheckErr(err)
46+
errs := l.Restore(target, from, force, snapshot, optional)
47+
for _, err := range errs {
48+
colors.Error.Printf("%s\n\n", err)
49+
}
50+
if len(errs) > 0 {
51+
CheckErr(fmt.Errorf("%d errors were found", len(errs)))
52+
}
4753
},
4854
}
4955

internal/location.go

+66-19
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,21 @@ type Hooks struct {
4242

4343
type LocationCopy = map[string][]string
4444

45-
type Location struct {
46-
name string `mapstructure:",omitempty"`
47-
From []string `mapstructure:"from,omitempty"`
48-
Type string `mapstructure:"type,omitempty"`
49-
To []string `mapstructure:"to,omitempty"`
45+
type Restore struct {
5046
Hooks Hooks `mapstructure:"hooks,omitempty"`
51-
Cron string `mapstructure:"cron,omitempty"`
52-
Options Options `mapstructure:"options,omitempty"`
53-
ForgetOption LocationForgetOption `mapstructure:"forget,omitempty"`
54-
CopyOption LocationCopy `mapstructure:"copy,omitempty"`
47+
}
48+
49+
type Location struct {
50+
name string `mapstructure:",omitempty"`
51+
From []string `mapstructure:"from,omitempty"`
52+
Type string `mapstructure:"type,omitempty"`
53+
To []string `mapstructure:"to,omitempty"`
54+
Hooks Hooks `mapstructure:"hooks,omitempty"`
55+
Cron string `mapstructure:"cron,omitempty"`
56+
Options Options `mapstructure:"options,omitempty"`
57+
ForgetOption LocationForgetOption `mapstructure:"forget,omitempty"`
58+
CopyOption LocationCopy `mapstructure:"copy,omitempty"`
59+
RestoreOption Restore `mapstructure:"restore,omitempty"`
5560
}
5661

5762
func GetLocation(name string) (Location, bool) {
@@ -366,11 +371,35 @@ func buildRestoreCommand(l Location, to string, snapshot string, options []strin
366371
return base
367372
}
368373

369-
func (l Location) Restore(to, from string, force bool, snapshot string, options []string) error {
374+
func (l Location) Restore(to, from string, force bool, snapshot string, options []string) (errors []error) {
375+
cwd, _ := GetPathRelativeToConfig(".")
376+
hooksOptions := ExecuteOptions{
377+
Command: "bash",
378+
Dir: cwd,
379+
Envs: map[string]string{
380+
"AUTORESTIC_LOCATION": l.name,
381+
},
382+
}
383+
384+
defer func() {
385+
var commands []string
386+
var isSuccess = len(errors) == 0
387+
if isSuccess {
388+
commands = l.RestoreOption.Hooks.Success
389+
} else {
390+
commands = l.RestoreOption.Hooks.Failure
391+
}
392+
if err := l.ExecuteHooks(commands, hooksOptions); err != nil {
393+
errors = append(errors, err)
394+
}
395+
396+
colors.Success.Println("Done")
397+
}()
398+
370399
if from == "" {
371400
from = l.To[0]
372401
} else if !l.hasBackend(from) {
373-
return fmt.Errorf("invalid backend: \"%s\"", from)
402+
errors = append(errors, fmt.Errorf("invalid backend: \"%s\"", from))
374403
}
375404

376405
if snapshot == "" {
@@ -381,15 +410,23 @@ func (l Location) Restore(to, from string, force bool, snapshot string, options
381410
backend, _ := GetBackend(from)
382411
colors.Secondary.Printf("Restoring %s@%s → %s\n", snapshot, backend.name, to)
383412

413+
// Before Hooks for restore
414+
if err := l.ExecuteHooks(l.RestoreOption.Hooks.Before, hooksOptions); err != nil {
415+
errors = append(errors, err)
416+
return
417+
}
418+
384419
t, err := l.getType()
385420
if err != nil {
386-
return err
421+
errors = append(errors, err)
422+
return
387423
}
388424
switch t {
389425
case TypeLocal:
390426
to, err = filepath.Abs(to)
391427
if err != nil {
392-
return err
428+
errors = append(errors, err)
429+
return
393430
}
394431
// Check if target is empty
395432
if !force {
@@ -398,14 +435,17 @@ func (l Location) Restore(to, from string, force bool, snapshot string, options
398435
if err == nil {
399436
files, err := ioutil.ReadDir(to)
400437
if err != nil {
401-
return err
438+
errors = append(errors, err)
439+
return
402440
}
403441
if len(files) > 0 {
404-
return notEmptyError
442+
errors = append(errors, notEmptyError)
443+
return
405444
}
406445
} else {
407446
if !os.IsNotExist(err) {
408-
return err
447+
errors = append(errors, err)
448+
return
409449
}
410450
}
411451
}
@@ -414,10 +454,17 @@ func (l Location) Restore(to, from string, force bool, snapshot string, options
414454
_, _, err = backend.ExecDocker(l, buildRestoreCommand(l, "/", snapshot, options))
415455
}
416456
if err != nil {
417-
return err
457+
errors = append(errors, err)
458+
return
418459
}
419-
colors.Success.Println("Done")
420-
return nil
460+
461+
// Before Hooks for restore
462+
if err := l.ExecuteHooks(l.RestoreOption.Hooks.After, hooksOptions); err != nil {
463+
errors = append(errors, err)
464+
return
465+
}
466+
467+
return
421468
}
422469

423470
func (l Location) RunCron() error {

0 commit comments

Comments
 (0)