Documentation
¶
Overview ¶
Package restore implements restore Path B: a user restoring their own Space from a snapshot, back into OpenCloud (decisions.md, "Restore paths").
[S3 target] -> [kopia read/decrypt] -> [CS3 upload]
It is the mirror image of internal/backup, and shares its rules:
- Authorization is the caller's, not the worker's: the API only ever hands this package a Space the caller is a *member* of. There is no admin path into a user's Space (decisions.md #2, #15) — being an admin grants nothing here.
- v1 restores a whole snapshot into a fresh "Restore/<timestamp>/" folder. Live data is never overwritten and never deleted (decisions.md #3).
- Nothing is staged on disk: entries stream from kopia straight into CS3, the same stance the backup path takes.
- The plaintext Data Key and the target's credentials exist only in memory for the duration of a run.
Index ¶
- Constants
- Variables
- func RestoreFolderName(at time.Time) string
- type Clock
- type Deps
- type Result
- type Runner
- func (r *Runner) ListSnapshots(ctx context.Context, spaceID string) ([]snapshot.Info, error)
- func (r *Runner) RunRestore(ctx context.Context, spaceID string, id snapshot.SnapshotID) (Result, error)
- func (r *Runner) StartRestore(ctx context.Context, spaceID string, id snapshot.SnapshotID) (string, error)
Constants ¶
const DefaultRunTimeout = 6 * time.Hour
DefaultRunTimeout bounds a background restore. Like a backup run it is generous: a full Space may be large and being killed halfway is worse than being slow.
const RestoreFolder = "Restore"
RestoreFolder is the top-level folder every restore lands in. A restore never touches live data, so everything is written below RestoreFolder/<timestamp>/.
Variables ¶
var ( // ErrSpaceNotFound means the worker credential cannot see the Space. ErrSpaceNotFound = errors.New("restore: space not found") // ErrNotConfigured means the Space has no backup configuration or no keys. ErrNotConfigured = errors.New("restore: backup is not configured for this space") ErrTargetUnavailable = errors.New("restore: backup target is unavailable") // ErrSnapshotNotFound means the requested snapshot is not in the repository. ErrSnapshotNotFound = errors.New("restore: no such snapshot") // ErrRunInProgress means another run holds the Space's lock. ErrRunInProgress = errors.New("restore: a run is already in progress for this space") // ErrRunFailed means the restore itself failed. ErrRunFailed = errors.New("restore: restore run failed") )
Sentinel errors the API maps onto status codes. Their messages are user-safe: they never name internal services, endpoints, or key material.
Functions ¶
func RestoreFolderName ¶
RestoreFolderName builds the space-relative folder a restore writes into: "Restore/<RFC3339 timestamp>". The timestamp is filename-safe on every platform the Space may later be synced to, so colons are replaced.
Types ¶
type Deps ¶
type Deps struct {
Spaces cs3.SpaceReader
Writer cs3.SpaceWriter
Configs spacecfg.Store
Targets targets.Store
Sealer targets.CredSealer
Keys keys.Store
Unwrap keys.Wrapper
Engine snapshot.Engine
Jobs jobs.Store
Locks jobs.Locker
// Logger receives operational detail: identifiers and counts, never key
// material and never a user's file names.
Logger *slog.Logger
// Clock is injected for deterministic tests and names the restore folder.
Clock Clock
// RunTimeout bounds a background run started by StartRestore.
RunTimeout time.Duration
// Outcome tunes how a run's terminal outcome is written. The zero value is
// the production setting; tests shorten the retry backoff.
Outcome jobs.RecordOptions
// Background owns the restores StartRestore puts in the background, so
// that shutdown cancels and waits for them. Optional: when nil the Runner
// keeps its own, which nothing stops — fine for tests, wrong for the service.
Background *jobs.Background
}
Deps are the Runner's injected collaborators; every one is an interface so a restore can be exercised without OpenCloud, S3, or real keys.
type Result ¶
type Result struct {
JobID string
SpaceID string
SnapshotID snapshot.SnapshotID
// Folder is the space-relative folder the snapshot was restored into.
Folder string
FileCount int64
TotalBytes int64
StartedAt time.Time
FinishedAt time.Time
}
Result summarises a completed restore. It carries no key material.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner executes restore runs.
func (*Runner) ListSnapshots ¶
ListSnapshots returns the snapshots available for a Space, newest first. It is what the restore picker reads; the caller must already have verified the requester's membership.
func (*Runner) RunRestore ¶
func (r *Runner) RunRestore(ctx context.Context, spaceID string, id snapshot.SnapshotID) (Result, error)
RunRestore performs one restore and waits for it to finish.
func (*Runner) StartRestore ¶
func (r *Runner) StartRestore(ctx context.Context, spaceID string, id snapshot.SnapshotID) (string, error)
StartRestore accepts a restore and runs it in the background, returning the job id to poll. Everything that can fail fast — the Space, the lock — is resolved before returning.