diff --git a/gen/go/v1/operations.pb.go b/gen/go/v1/operations.pb.go index b772b5ce..a8dee5cd 100644 --- a/gen/go/v1/operations.pb.go +++ b/gen/go/v1/operations.pb.go @@ -77,6 +77,7 @@ const ( OperationStatus_STATUS_PENDING OperationStatus = 1 // used to indicate that the operation is pending. OperationStatus_STATUS_INPROGRESS OperationStatus = 2 // used to indicate that the operation is in progress. OperationStatus_STATUS_SUCCESS OperationStatus = 3 // used to indicate that the operation completed successfully. + OperationStatus_STATUS_WARNING OperationStatus = 7 // used to indicate that the operation completed with warnings. OperationStatus_STATUS_ERROR OperationStatus = 4 // used to indicate that the operation failed. OperationStatus_STATUS_SYSTEM_CANCELLED OperationStatus = 5 // indicates operation cancelled by the system. OperationStatus_STATUS_USER_CANCELLED OperationStatus = 6 // indicates operation cancelled by the user. @@ -89,6 +90,7 @@ var ( 1: "STATUS_PENDING", 2: "STATUS_INPROGRESS", 3: "STATUS_SUCCESS", + 7: "STATUS_WARNING", 4: "STATUS_ERROR", 5: "STATUS_SYSTEM_CANCELLED", 6: "STATUS_USER_CANCELLED", @@ -98,6 +100,7 @@ var ( "STATUS_PENDING": 1, "STATUS_INPROGRESS": 2, "STATUS_SUCCESS": 3, + "STATUS_WARNING": 7, "STATUS_ERROR": 4, "STATUS_SYSTEM_CANCELLED": 5, "STATUS_USER_CANCELLED": 6, @@ -798,21 +801,22 @@ var file_v1_operations_proto_rawDesc = []byte{ 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, - 0x10, 0x02, 0x2a, 0xae, 0x01, 0x0a, 0x0f, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x10, 0x02, 0x2a, 0xc2, 0x01, 0x0a, 0x0f, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, - 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x43, 0x41, 0x4e, - 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, - 0x44, 0x10, 0x06, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x72, - 0x65, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x12, 0x10, 0x0a, + 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, + 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, + 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x43, 0x41, 0x4e, 0x43, + 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, + 0x67, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/go.mod b/go.mod index e1bbb905..14431c14 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/garethgeorge/restora -go 1.21.3 +go 1.21 require ( github.com/GeertJohan/go.rice v1.0.3 diff --git a/internal/orchestrator/taskbackup.go b/internal/orchestrator/taskbackup.go index 241399d0..620a4396 100644 --- a/internal/orchestrator/taskbackup.go +++ b/internal/orchestrator/taskbackup.go @@ -2,6 +2,7 @@ package orchestrator import ( "context" + "errors" "fmt" "time" @@ -123,7 +124,11 @@ func backupHelper(ctx context.Context, orchestrator *Orchestrator, plan *v1.Plan } }) if err != nil { - return fmt.Errorf("repo.Backup for repo %q: %w", plan.Repo, err) + if !errors.Is(err, restic.ErrPartialBackup) { + return fmt.Errorf("repo.Backup for repo %q: %w", plan.Repo, err) + } + op.Status = v1.OperationStatus_STATUS_WARNING + op.DisplayMessage = "Partial backup, some files may not have been read completely." } op.SnapshotId = summary.SnapshotId diff --git a/pkg/restic/restic.go b/pkg/restic/restic.go index 0499892f..7a952b1f 100644 --- a/pkg/restic/restic.go +++ b/pkg/restic/restic.go @@ -16,6 +16,8 @@ import ( ) var errAlreadyInitialized = errors.New("repo already initialized") +var ErrPartialBackup = errors.New("incomplete backup") +var ErrBackupFailed = errors.New("backup failed") type Repo struct { mu sync.Mutex @@ -133,6 +135,15 @@ func (r *Repo) Backup(ctx context.Context, progressCallback func(*BackupProgress defer writer.Close() defer wg.Done() if err := cmd.Wait(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if exitErr.ExitCode() == 1 { + cmdErr = ErrPartialBackup + } else { + cmdErr = fmt.Errorf("exit code %v: %w", exitErr.ExitCode(), ErrBackupFailed) + } + return + } cmdErr = err } }() diff --git a/proto/v1/operations.proto b/proto/v1/operations.proto index e246a742..c38feb30 100644 --- a/proto/v1/operations.proto +++ b/proto/v1/operations.proto @@ -55,6 +55,7 @@ enum OperationStatus { STATUS_PENDING = 1; // used to indicate that the operation is pending. STATUS_INPROGRESS = 2; // used to indicate that the operation is in progress. STATUS_SUCCESS = 3; // used to indicate that the operation completed successfully. + STATUS_WARNING = 7; // used to indicate that the operation completed with warnings. STATUS_ERROR = 4; // used to indicate that the operation failed. STATUS_SYSTEM_CANCELLED = 5; // indicates operation cancelled by the system. STATUS_USER_CANCELLED = 6; // indicates operation cancelled by the user. diff --git a/webui/gen/ts/v1/operations.pb.ts b/webui/gen/ts/v1/operations.pb.ts index 1f6eee3b..03e8631e 100644 --- a/webui/gen/ts/v1/operations.pb.ts +++ b/webui/gen/ts/v1/operations.pb.ts @@ -27,6 +27,7 @@ export enum OperationStatus { STATUS_PENDING = "STATUS_PENDING", STATUS_INPROGRESS = "STATUS_INPROGRESS", STATUS_SUCCESS = "STATUS_SUCCESS", + STATUS_WARNING = "STATUS_WARNING", STATUS_ERROR = "STATUS_ERROR", STATUS_SYSTEM_CANCELLED = "STATUS_SYSTEM_CANCELLED", STATUS_USER_CANCELLED = "STATUS_USER_CANCELLED", diff --git a/webui/src/state/oplog.ts b/webui/src/state/oplog.ts index 4ac16098..38e11631 100644 --- a/webui/src/state/oplog.ts +++ b/webui/src/state/oplog.ts @@ -301,6 +301,10 @@ export const detailsForOperation = ( state = "error"; color = "red"; break; + case OperationStatus.STATUS_WARNING: + state = "warning"; + color = "orange"; + break; case OperationStatus.STATUS_SUCCESS: state = ""; color = "green";