tracking: implement restore for additional services
- Dominant language
- Rust
- Stars
- 5.4k
- Forks
- 825
- Avg merge
- 1d 14m
- Merged PRs (30d)
- 127
Description
## Context
[`Operator::restore`](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/core/src/docs/rfcs/7182_restore_api.md) and the first S3 implementation landed in #8143. This issue turns the API discussion in #4321 into a service implementation tracker.
The checklist includes services whose providers expose versioning, delete markers, soft deletion, revisions, or a recycle bin. Other services should keep returning `Unsupported` until a provider-native recoverable state is identified.
## Contract
Each implementation must preserve the public restore contract:
- `restore(path)` succeeds for a live object, restores the latest service-native deleted state, and returns `NotFound` when no live or recoverable state exists.
- `restore_with(path).version(version)` makes the selected historical version current.
- `if_not_exists` is advertised only when the provider offers an atomic destination condition.
- One restore call reverses one provider-native deletion state. For services that stack delete markers, repeated calls may expose progressively older states.
- Capabilities must reflect the configured provider and must not be inferred only from a compatible API shape.
## Status
### Completed
- [x] **S3** — #8143 implements current delete-marker removal and version-selected server-side copy. S3 Express keeps restore capabilities disabled because it does not support versioning.
### Version and delete-marker services
- [ ] **COS** — OpenDAL already exposes versioned stat/read/delete/list and deleted-entry listing ([capabilities](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/services/cos/src/backend.rs#L228-L274)). Implement path restore by deleting the current delete marker, and selected-version restore with `CopyObject`'s source `versionId` ([COS API](https://intl.cloud.tencent.com/document/api/436/10881)). Do not advertise conditional restore until an atomic versioned-destination condition is proven against COS.
- [ ] **OSS** — OpenDAL already exposes versioned stat/read/delete/list and deleted-entry listing ([capabilities](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/services/oss/src/backend.rs#L553-L604)). OSS documents marker removal by version ID ([delete markers](https://www.alibabacloud.com/help/en/oss/user-guide/delete-marker)) and source-version copy ([CopyObject](https://www.alibabacloud.com/help/en/oss/developer-reference/copyobject)); implement base and selected-version restore.
- [ ] **TOS** — OpenDAL already exposes versioned stat/read/delete/list and deleted-entry listing ([capabilities](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/services/tos/src/backend.rs#L168-L217)). Base restore can delete the current marker. Verify TOS's source-version `CopyObject` protocol against the actual service before advertising `restore_with_version`.
- [ ] **OBS** — OBS supports versioning, delete markers, and undelete ([OBS User Guide](https://support.huaweicloud.com/intl/en-us/ugobs-obs/obs-usermanual-en-pdf.pdf), “Undeleting an Object”). OpenDAL does not yet expose OBS version list/read/delete/copy primitives, so add those prerequisites before restore.
### Native soft-delete, revision, and recycle-bin services
- [ ] **Azure Blob** — Use `Undelete Blob` for soft-delete-only accounts ([REST API](https://learn.microsoft.com/en-us/rest/api/storageservices/undelete-blob)). With blob versioning, discover a previous version and copy it to the base blob ([versioning behavior](https://learn.microsoft.com/en-us/azure/storage/blobs/versioning-overview)). OpenDAL's copy request already accepts a source `versionid` ([source](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/services/azblob/src/core.rs#L772-L784)). #7178 predates the current `restore` API and must be adapted before it can land.
- [ ] **GCS** — Restore a noncurrent generation by rewriting it to the live object ([Object Versioning](https://docs.cloud.google.com/storage/docs/object-versioning)); restore a soft-deleted generation with `objects.restore`, including `restoreToken` when hierarchical namespace requires it ([JSON API](https://docs.cloud.google.com/storage/docs/json_api/v1/objects/restore)). OpenDAL rewrite already supports `sourceGeneration` and `ifGenerationMatch=0` ([source](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/services/gcs/src/core.rs#L524-L536)), but it still needs generation/deleted-state discovery.
- [ ] **Backblaze B2** — Discover `hide` entries with `b2_list_file_versions` ([API](https://www.backblaze.com/apidocs/b2-list-file-versions)), remove the current hide marker with `b2_delete_file_version`, and promote a selected file ID with `b2_copy_file` ([API](https://www.backblaze.com/apidocs/b2-copy-file)). OpenDAL currently lacks the required version-listing capability.
- [ ] **Dropbox** — Discover a restorable revision and call `files/restore(path, rev)` ([official SDK/API reference](https://dropbox.github.io/dropbox-sdk-js/Dropbox.html#filesRestore__anchor)). OpenDAL currently does not expose Dropbox revisions, so define how revision IDs reach `restore_with(...).version(...)` and verify behavior against the service.
- [ ] **Google Drive** — OpenDAL delete already moves files to trash ([source](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/services/gdrive/src/core.rs#L421-L434)). Restore by finding the trashed item and setting `trashed=false` ([Drive API guide](https://developers.google.com/workspace/drive/api/guides/delete)). The implementation needs deleted-path-to-file-ID resolution and explicit destination-conflict semantics.
- [ ] **OneDrive** — Microsoft Graph supports restoring a recycle-bin item ([driveItem restore](https://learn.microsoft.com/en-us/graph/api/driveitem-restore?view=graph-rest-1.0)) and promoting an older version ([driveItemVersion restore](https://learn.microsoft.com/en-us/graph/api/driveitemversion-restoreversion?view=graph-rest-1.0)). OpenDAL already lists versions but needs stable deleted-item ID resolution for path restore.
### Investigation or blocked
- [ ] **Aliyun Drive** — Verify the exact consumer Alipan Open API used by OpenDAL. PDS recycle-bin documentation does not establish that this backend exposes the same restore endpoint or retention behavior.
- [ ] **Yandex Disk** — OpenDAL currently deletes with `permanently=true` ([source](https://github.com/apache/opendal/blob/26998a9bc47c956a6078aa5325448deb7de630ab/core/services/yandex-disk/src/core.rs#L270-L280)). Restore is blocked until a separate decision changes or parameterizes delete semantics; restore work must not silently change existing delete behavior.
## Pull request acceptance checklist
Every service PR should cover the applicable items:
- [ ] Advertise only capabilities verified for the configured provider.
- [ ] Succeed when the path is already live.
- [ ] Restore one recoverable deleted state.
- [ ] Return `NotFound` for an unknown or permanently deleted path.
- [ ] Promote the selected version when `restore_with_version` is advertised.
- [ ] Prove both success and conflict behavior against the actual service when `restore_with_if_not_exists` is advertised.
- [ ] Verify repeated deletion/restoration behavior when the provider stacks markers or revisions.
- [ ] Add actual-service behavior coverage and preset configuration.
- [ ] Document provider-specific prerequisites and limitations.
Provider documentation and request-construction analysis establish feasibility, but they do not replace actual-service behavior tests.
## Non-goals
- Changing a service's existing delete semantics inside a restore PR.
- Downloading and re-uploading object data when the provider offers native server-side recovery or copy.
- Claiming recovery for unversioned, expired, or permanently deleted data.
Contributor guide
Research direction
Choose one unchecked provider, then read its cited backend.rs or core.rs entry point and the linked provider API documentation. Verify the provider's recovery and capability behavior with actual-service tests and preset configuration. Done means the applicable acceptance checklist passes without changing existing delete semantics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, google-cloud, rust
- Domain
- api, backend, cloud
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100