mirror of
https://github.com/garethgeorge/backrest.git
synced 2026-08-25 02:16:38 +00:00
fix: support more versions of restic
This commit is contained in:
@@ -8,8 +8,9 @@ import (
|
||||
)
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
// t.Parallel()
|
||||
log, err := NewOpLog(t.TempDir() + "/test.boltdb")
|
||||
t.Cleanup(func() { log.Close() })
|
||||
if err != nil {
|
||||
t.Fatalf("error creating oplog: %s", err)
|
||||
}
|
||||
@@ -19,16 +20,16 @@ func TestCreate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddOperation(t *testing.T) {
|
||||
t.Parallel()
|
||||
// t.Parallel()
|
||||
log, err := NewOpLog(t.TempDir() + "/test.boltdb")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating oplog: %s", err)
|
||||
}
|
||||
defer log.Close()
|
||||
t.Cleanup(func() { log.Close() })
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
op *v1.Operation
|
||||
name string
|
||||
op *v1.Operation
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -65,8 +66,7 @@ func TestAddOperation(t *testing.T) {
|
||||
op: &v1.Operation{
|
||||
Id: 0,
|
||||
Op: &v1.Operation_OperationIndexSnapshot{
|
||||
OperationIndexSnapshot: &v1.OperationIndexSnapshot{
|
||||
},
|
||||
OperationIndexSnapshot: &v1.OperationIndexSnapshot{},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
@@ -82,17 +82,17 @@ func TestAddOperation(t *testing.T) {
|
||||
{
|
||||
name: "operation with repo",
|
||||
op: &v1.Operation{
|
||||
Id: 0,
|
||||
Id: 0,
|
||||
RepoId: "testrepo",
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "operation with plan",
|
||||
op: &v1.Operation{
|
||||
Id: 0,
|
||||
Id: 0,
|
||||
PlanId: "testplan",
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -112,31 +112,32 @@ func TestAddOperation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListOperation(t *testing.T) {
|
||||
t.Parallel()
|
||||
// t.Parallel()
|
||||
log, err := NewOpLog(t.TempDir() + "/test.boltdb")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating oplog: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { log.Close() })
|
||||
|
||||
// these should get assigned IDs 1-3 respectively by the oplog
|
||||
ops := []*v1.Operation{
|
||||
{
|
||||
PlanId: "plan1",
|
||||
RepoId: "repo1",
|
||||
PlanId: "plan1",
|
||||
RepoId: "repo1",
|
||||
DisplayMessage: "op1",
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
},
|
||||
{
|
||||
PlanId: "plan1",
|
||||
RepoId: "repo2",
|
||||
PlanId: "plan1",
|
||||
RepoId: "repo2",
|
||||
DisplayMessage: "op2",
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
},
|
||||
{
|
||||
PlanId: "plan2",
|
||||
RepoId: "repo2",
|
||||
PlanId: "plan2",
|
||||
RepoId: "repo2",
|
||||
DisplayMessage: "op3",
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -147,34 +148,34 @@ func TestListOperation(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
byPlan bool
|
||||
byRepo bool
|
||||
id string
|
||||
name string
|
||||
byPlan bool
|
||||
byRepo bool
|
||||
id string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "list plan1",
|
||||
byPlan: true,
|
||||
id: "plan1",
|
||||
name: "list plan1",
|
||||
byPlan: true,
|
||||
id: "plan1",
|
||||
expected: []string{"op1", "op2"},
|
||||
},
|
||||
{
|
||||
name: "list plan2",
|
||||
byPlan: true,
|
||||
id: "plan2",
|
||||
name: "list plan2",
|
||||
byPlan: true,
|
||||
id: "plan2",
|
||||
expected: []string{"op3"},
|
||||
},
|
||||
{
|
||||
name: "list repo1",
|
||||
byRepo: true,
|
||||
id: "repo1",
|
||||
name: "list repo1",
|
||||
byRepo: true,
|
||||
id: "repo1",
|
||||
expected: []string{"op1"},
|
||||
},
|
||||
{
|
||||
name: "list repo2",
|
||||
byRepo: true,
|
||||
id: "repo2",
|
||||
name: "list repo2",
|
||||
byRepo: true,
|
||||
id: "repo2",
|
||||
expected: []string{"op2", "op3"},
|
||||
},
|
||||
}
|
||||
@@ -182,7 +183,7 @@ func TestListOperation(t *testing.T) {
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// t.Parallel()
|
||||
var ops []*v1.Operation
|
||||
var err error
|
||||
if tc.byPlan {
|
||||
@@ -204,17 +205,18 @@ func TestListOperation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBigIO(t *testing.T) {
|
||||
t.Parallel()
|
||||
// t.Parallel()
|
||||
log, err := NewOpLog(t.TempDir() + "/test.boltdb")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating oplog: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { log.Close() })
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
for i := 0; i < 100; i++ {
|
||||
if err := log.Add(&v1.Operation{
|
||||
PlanId: "plan1",
|
||||
RepoId: "repo1",
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
Op: &v1.Operation_OperationBackup{},
|
||||
}); err != nil {
|
||||
t.Fatalf("error adding operation: %s", err)
|
||||
}
|
||||
@@ -224,16 +226,16 @@ func TestBigIO(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("error listing operations: %s", err)
|
||||
}
|
||||
if len(ops) != 1000 {
|
||||
t.Errorf("want 1000 operations, got %d", len(ops))
|
||||
if len(ops) != 100 {
|
||||
t.Errorf("want 100 operations, got %d", len(ops))
|
||||
}
|
||||
|
||||
ops, err = log.GetByRepo("repo1", FilterKeepAll())
|
||||
if err != nil {
|
||||
t.Fatalf("error listing operations: %s", err)
|
||||
}
|
||||
if len(ops) != 1000 {
|
||||
t.Errorf("want 1000 operations, got %d", len(ops))
|
||||
if len(ops) != 100 {
|
||||
t.Errorf("want 100 operations, got %d", len(ops))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +245,7 @@ func TestIndexSnapshot(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("error creating oplog: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { log.Close() })
|
||||
|
||||
op := &v1.Operation{
|
||||
PlanId: "plan1",
|
||||
@@ -266,7 +269,7 @@ func TestIndexSnapshot(t *testing.T) {
|
||||
if id != op.Id {
|
||||
t.Fatalf("want id %d, got %d", op.Id, id)
|
||||
}
|
||||
|
||||
|
||||
id, err = log.HasIndexedSnapshot("notfound")
|
||||
if err != nil {
|
||||
t.Fatalf("error checking for snapshot: %s", err)
|
||||
@@ -282,4 +285,4 @@ func collectMessages(ops []*v1.Operation) []string {
|
||||
messages = append(messages, op.DisplayMessage)
|
||||
}
|
||||
return messages
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package orchestrator
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -18,36 +17,32 @@ type RepoOrchestrator struct {
|
||||
mu sync.Mutex
|
||||
|
||||
repoConfig *v1.Repo
|
||||
repo *restic.Repo
|
||||
repo *restic.Repo
|
||||
}
|
||||
|
||||
func newRepoOrchestrator(repoConfig *v1.Repo, repo *restic.Repo) *RepoOrchestrator {
|
||||
return &RepoOrchestrator{
|
||||
repoConfig: repoConfig,
|
||||
repo: repo,
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RepoOrchestrator) Snapshots(ctx context.Context) ([]*restic.Snapshot, error) {
|
||||
snapshots, err := r.repo.Snapshots(ctx, restic.WithFlags("--latest", "1000"))
|
||||
snapshots, err := r.repo.Snapshots(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("restic.Snapshots: %w", err)
|
||||
return nil, fmt.Errorf("get snapshots for repo %v: %w", r.repoConfig.Id, err)
|
||||
}
|
||||
|
||||
sort.SliceStable(snapshots, func(i, j int) bool {
|
||||
return snapshots[i].UnixTimeMs() < snapshots[j].UnixTimeMs()
|
||||
})
|
||||
|
||||
sortSnapshotsByTime(snapshots)
|
||||
return snapshots, nil
|
||||
}
|
||||
|
||||
func (r *RepoOrchestrator) SnapshotsForPlan(ctx context.Context, plan *v1.Plan) ([]*restic.Snapshot, error) {
|
||||
snapshots, err := r.Snapshots(ctx)
|
||||
snapshots, err := r.repo.Snapshots(ctx, restic.WithFlags("--tag", tagForPlan(plan)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("get snapshots for plan %q: %w", plan.Id, err)
|
||||
}
|
||||
|
||||
return filterSnapshotsForPlan(snapshots, plan), nil
|
||||
sortSnapshotsByTime(snapshots)
|
||||
return snapshots, nil
|
||||
}
|
||||
|
||||
func (r *RepoOrchestrator) Backup(ctx context.Context, plan *v1.Plan, progressCallback func(event *restic.BackupProgressEntry)) (*restic.BackupProgressEntry, error) {
|
||||
@@ -71,7 +66,7 @@ func (r *RepoOrchestrator) Backup(ctx context.Context, plan *v1.Plan, progressCa
|
||||
|
||||
if len(snapshots) > 0 {
|
||||
// TODO: design a test strategy to verify that the backup parent is used correctly.
|
||||
opts = append(opts, restic.WithBackupParent(snapshots[len(snapshots) - 1].Id))
|
||||
opts = append(opts, restic.WithBackupParent(snapshots[len(snapshots)-1].Id))
|
||||
}
|
||||
|
||||
summary, err := r.repo.Backup(ctx, progressCallback, opts...)
|
||||
@@ -100,22 +95,12 @@ func (r *RepoOrchestrator) ListSnapshotFiles(ctx context.Context, snapshotId str
|
||||
return lsEnts, nil
|
||||
}
|
||||
|
||||
func filterSnapshotsForPlan(snapshots []*restic.Snapshot, plan *v1.Plan) []*restic.Snapshot {
|
||||
wantTag := tagForPlan(plan)
|
||||
var filtered []*restic.Snapshot
|
||||
for _, snapshot := range snapshots {
|
||||
if snapshot.Tags == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if slices.Contains(snapshot.Tags, wantTag) {
|
||||
filtered = append(filtered, snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func tagForPlan(plan *v1.Plan) string {
|
||||
return fmt.Sprintf("plan:%s", plan.Id)
|
||||
}
|
||||
|
||||
func sortSnapshotsByTime(snapshots []*restic.Snapshot) {
|
||||
sort.SliceStable(snapshots, func(i, j int) bool {
|
||||
return snapshots[i].UnixTimeMs() < snapshots[j].UnixTimeMs()
|
||||
})
|
||||
}
|
||||
|
||||
Generated
+1098
-2948
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user