From fe6c6f2373df9a6d0feb4c96c6346665a93d0d75 Mon Sep 17 00:00:00 2001 From: cupcakearmy Date: Tue, 12 Apr 2022 21:37:35 +0200 Subject: [PATCH] error codes --- internal/backend.go | 19 +++++++++---------- internal/bins/bins.go | 2 +- internal/location.go | 28 +++++++++++++++++----------- internal/metadata/metadata.go | 2 ++ internal/utils.go | 14 +++++++++----- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/internal/backend.go b/internal/backend.go index ebb004d..b90d7ce 100644 --- a/internal/backend.go +++ b/internal/backend.go @@ -122,13 +122,13 @@ func (b Backend) validate() error { } options := ExecuteOptions{Envs: env} // Check if already initialized - _, err = ExecuteResticCommand(options, "snapshots") + _, _, err = ExecuteResticCommand(options, "snapshots") if err == nil { return nil } else { // If not initialize colors.Body.Printf("Initializing backend \"%s\"...\n", b.name) - out, err := ExecuteResticCommand(options, "init") + _, out, err := ExecuteResticCommand(options, "init") if flags.VERBOSE { colors.Faint.Println(out) } @@ -142,7 +142,7 @@ func (b Backend) Exec(args []string) error { return err } options := ExecuteOptions{Envs: env} - out, err := ExecuteResticCommand(options, args...) + _, out, err := ExecuteResticCommand(options, args...) if err != nil { colors.Error.Println(out) return err @@ -153,10 +153,10 @@ func (b Backend) Exec(args []string) error { return nil } -func (b Backend) ExecDocker(l Location, args []string) (string, error) { +func (b Backend) ExecDocker(l Location, args []string) (int, string, error) { env, err := b.getEnv() if err != nil { - return "", err + return -1, "", err } volume := l.From[0] options := ExecuteOptions{ @@ -188,20 +188,19 @@ func (b Backend) ExecDocker(l Location, args []string) (string, error) { // No additional setup needed case "rclone": // Read host rclone config and mount it into the container - configFile, err := ExecuteCommand(ExecuteOptions{Command: "rclone"}, "config", "file") + code, configFile, err := ExecuteCommand(ExecuteOptions{Command: "rclone"}, "config", "file") if err != nil { - return "", err + return code, "", err } splitted := strings.Split(strings.TrimSpace(configFile), "\n") configFilePath := splitted[len(splitted)-1] docker = append(docker, "--volume", configFilePath+":"+"/root/.config/rclone/rclone.conf:ro") default: - return "", fmt.Errorf("Backend type \"%s\" is not supported as volume endpoint", b.Type) + return -1, "", fmt.Errorf("Backend type \"%s\" is not supported as volume endpoint", b.Type) } for key, value := range env { docker = append(docker, "--env", key+"="+value) } docker = append(docker, "cupcakearmy/autorestic:"+VERSION, "-c", strings.Join(args, " ")) - out, err := ExecuteCommand(options, docker...) - return out, err + return ExecuteCommand(options, docker...) } diff --git a/internal/bins/bins.go b/internal/bins/bins.go index 2d90667..104efcb 100644 --- a/internal/bins/bins.go +++ b/internal/bins/bins.go @@ -128,7 +128,7 @@ func InstallRestic() error { } func upgradeRestic() error { - out, err := internal.ExecuteCommand(internal.ExecuteOptions{ + _, out, err := internal.ExecuteCommand(internal.ExecuteOptions{ Command: "restic", }, "self-update") colors.Faint.Println(out) diff --git a/internal/location.go b/internal/location.go index fcf8d0e..da589ec 100644 --- a/internal/location.go +++ b/internal/location.go @@ -104,7 +104,7 @@ func (l Location) ExecuteHooks(commands []string, options ExecuteOptions) error colors.Secondary.Println("\nRunning hooks") for _, command := range commands { colors.Body.Println("> " + command) - out, err := ExecuteCommand(options, "-c", command) + _, out, err := ExecuteCommand(options, "-c", command) if err != nil { colors.Error.Println(out) return err @@ -195,6 +195,7 @@ func (l Location) Backup(cron bool, specificBackend string) []error { Envs: env, } + var code int = 0 var out string switch t { case TypeLocal: @@ -206,7 +207,7 @@ func (l Location) Backup(cron bool, specificBackend string) []error { } cmd = append(cmd, path) } - out, err = ExecuteResticCommand(backupOptions, cmd...) + code, out, err = ExecuteResticCommand(backupOptions, cmd...) case TypeVolume: ok := CheckIfVolumeExists(l.From[0]) if !ok { @@ -214,20 +215,25 @@ func (l Location) Backup(cron bool, specificBackend string) []error { continue } cmd = append(cmd, "/data") - out, err = backend.ExecDocker(l, cmd) + code, out, err = backend.ExecDocker(l, cmd) } + + // Extract metadata + md := metadata.ExtractMetadataFromBackupLog(out) + md.ExitCode = fmt.Sprint(code) + mdEnv := metadata.MakeEnvFromMetadata(&md) + for k, v := range mdEnv { + options.Envs[k+"_"+fmt.Sprint(i)] = v + options.Envs[k+"_"+strings.ToUpper(backend.name)] = v + } + + // If error save it and continue if err != nil { colors.Error.Println(out) errors = append(errors, fmt.Errorf("%s@%s:\n%s%s", l.name, backend.name, out, err)) continue } - md := metadata.ExtractMetadataFromBackupLog(out) - mdEnv := metadata.MakeEnvFromMetadata(&md) - for k, v := range mdEnv { - options.Envs[k+"_"+fmt.Sprint(i)] = v - options.Envs[k+"_"+strings.ToUpper(backend.name)] = v - } if flags.VERBOSE { colors.Faint.Println(out) } @@ -276,7 +282,7 @@ func (l Location) Forget(prune bool, dry bool) error { cmd = append(cmd, "--dry-run") } cmd = append(cmd, combineOptions("forget", l, backend)...) - out, err := ExecuteResticCommand(options, cmd...) + _, out, err := ExecuteResticCommand(options, cmd...) if flags.VERBOSE { colors.Faint.Println(out) } @@ -348,7 +354,7 @@ func (l Location) Restore(to, from string, force bool, snapshot string, options } err = backend.Exec(buildRestoreCommand(l, to, snapshot, options)) case TypeVolume: - _, err = backend.ExecDocker(l, buildRestoreCommand(l, "/", snapshot, options)) + _, _, err = backend.ExecDocker(l, buildRestoreCommand(l, "/", snapshot, options)) } if err != nil { return err diff --git a/internal/metadata/metadata.go b/internal/metadata/metadata.go index 228cf22..308058c 100644 --- a/internal/metadata/metadata.go +++ b/internal/metadata/metadata.go @@ -21,6 +21,7 @@ type BackupLogMetadata struct { AddedSize string Processed BackupLogMetadataProcessed SnapshotID string + ExitCode string } type MetadatExtractor interface { @@ -67,6 +68,7 @@ func MakeEnvFromMetadata(metadata *BackupLogMetadata) map[string]string { env[prefix+"PROCESSED_FILES"] = metadata.Processed.Files env[prefix+"PROCESSED_SIZE"] = metadata.Processed.Size env[prefix+"PROCESSED_DURATION"] = metadata.Processed.Duration + env[prefix+"EXIT_CODE"] = metadata.ExitCode return env } diff --git a/internal/utils.go b/internal/utils.go index de6b167..8f12077 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -28,7 +28,7 @@ type ExecuteOptions struct { Dir string } -func ExecuteCommand(options ExecuteOptions, args ...string) (string, error) { +func ExecuteCommand(options ExecuteOptions, args ...string) (int, string, error) { cmd := exec.Command(options.Command, args...) env := os.Environ() for k, v := range options.Envs { @@ -47,12 +47,16 @@ func ExecuteCommand(options ExecuteOptions, args ...string) (string, error) { cmd.Stderr = &error err := cmd.Run() if err != nil { - return error.String(), err + if exitError, ok := err.(*exec.ExitError); ok { + return exitError.ExitCode(), error.String(), err + } else { + return -1, error.String(), err + } } - return out.String(), nil + return 0, out.String(), nil } -func ExecuteResticCommand(options ExecuteOptions, args ...string) (string, error) { +func ExecuteResticCommand(options ExecuteOptions, args ...string) (int, string, error) { options.Command = RESTIC_BIN var c = GetConfig() var optionsAsString = getOptions(c.Global, "") @@ -80,6 +84,6 @@ func CopyFile(from, to string) error { } func CheckIfVolumeExists(volume string) bool { - _, err := ExecuteCommand(ExecuteOptions{Command: "docker"}, "volume", "inspect", volume) + _, _, err := ExecuteCommand(ExecuteOptions{Command: "docker"}, "volume", "inspect", volume) return err == nil }