Add root parameter to backup/snapshot REST API
API Enhancement: - All snapshot endpoints now accept 'root' query parameter - Default root: /data (for production) - Test root: configurable (e.g., /tmp/backup_test) Endpoints updated: - GET /api/v2/snapshots?root=<path> - POST /api/v2/snapshots/:name?root=<path> - DELETE /api/v2/snapshots/:name?root=<path> - POST /api/v2/snapshots/:name/restore?root=<path> - GET /api/v2/storage/stats?root=<path> Integration Testing Results ✅: - Create snapshot: test_snap1 created - List snapshots: ['test_snap1'] returned - Modify file: 'original content' → 'modified content' - Restore snapshot: 'modified content' → 'original content' ✅ - Delete snapshot: test_snap1 removed Snapshot metadata format: { 'name': 'test_snap1', 'created': {'secs_since_epoch': 1782243041, 'nanos_since_epoch': 344384000}, 'source_path': '/tmp/backup_test' } Build: 495 tests pass Server: Port 11438 running with root parameter support
This commit is contained in:
BIN
data/auth.sqlite
BIN
data/auth.sqlite
Binary file not shown.
@@ -2821,45 +2821,54 @@ async fn run_backup_handler() -> Json<serde_json::Value> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_snapshots_handler() -> Json<Vec<String>> {
|
async fn list_snapshots_handler(Query(params): Query<std::collections::HashMap<String, String>>) -> Json<Vec<String>> {
|
||||||
|
let root = params.get("root").map(|p| PathBuf::from(p)).unwrap_or_else(|| PathBuf::from("/data"));
|
||||||
let backend = LocalFs::new();
|
let backend = LocalFs::new();
|
||||||
let root = PathBuf::from("/data");
|
|
||||||
match backend.list_snapshots(&root) {
|
match backend.list_snapshots(&root) {
|
||||||
Ok(list) => Json(list),
|
Ok(list) => Json(list),
|
||||||
Err(_) => Json(Vec::new()),
|
Err(_) => Json(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_snapshot_handler(Path(name): Path<String>) -> Json<serde_json::Value> {
|
async fn create_snapshot_handler(
|
||||||
|
Path(name): Path<String>,
|
||||||
|
Query(params): Query<std::collections::HashMap<String, String>>,
|
||||||
|
) -> Json<serde_json::Value> {
|
||||||
|
let root = params.get("root").map(|p| PathBuf::from(p)).unwrap_or_else(|| PathBuf::from("/data"));
|
||||||
let backend = LocalFs::new();
|
let backend = LocalFs::new();
|
||||||
let root = PathBuf::from("/data");
|
|
||||||
match backend.create_snapshot(&root, &name) {
|
match backend.create_snapshot(&root, &name) {
|
||||||
Ok(_) => Json(serde_json::json!({"success": true, "name": name})),
|
Ok(_) => Json(serde_json::json!({"success": true, "name": name})),
|
||||||
Err(e) => Json(serde_json::json!({"success": false, "error": e.to_string()})),
|
Err(e) => Json(serde_json::json!({"success": false, "error": e.to_string()})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_snapshot_handler(Path(name): Path<String>) -> Json<serde_json::Value> {
|
async fn delete_snapshot_handler(
|
||||||
|
Path(name): Path<String>,
|
||||||
|
Query(params): Query<std::collections::HashMap<String, String>>,
|
||||||
|
) -> Json<serde_json::Value> {
|
||||||
|
let root = params.get("root").map(|p| PathBuf::from(p)).unwrap_or_else(|| PathBuf::from("/data"));
|
||||||
let backend = LocalFs::new();
|
let backend = LocalFs::new();
|
||||||
let root = PathBuf::from("/data");
|
|
||||||
match backend.delete_snapshot(&root, &name) {
|
match backend.delete_snapshot(&root, &name) {
|
||||||
Ok(_) => Json(serde_json::json!({"success": true, "name": name})),
|
Ok(_) => Json(serde_json::json!({"success": true, "name": name})),
|
||||||
Err(e) => Json(serde_json::json!({"success": false, "error": e.to_string()})),
|
Err(e) => Json(serde_json::json!({"success": false, "error": e.to_string()})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn restore_snapshot_handler(Path(name): Path<String>) -> Json<serde_json::Value> {
|
async fn restore_snapshot_handler(
|
||||||
|
Path(name): Path<String>,
|
||||||
|
Query(params): Query<std::collections::HashMap<String, String>>,
|
||||||
|
) -> Json<serde_json::Value> {
|
||||||
|
let root = params.get("root").map(|p| PathBuf::from(p)).unwrap_or_else(|| PathBuf::from("/data"));
|
||||||
let backend = LocalFs::new();
|
let backend = LocalFs::new();
|
||||||
let root = PathBuf::from("/data");
|
|
||||||
match backend.restore_snapshot(&root, &name) {
|
match backend.restore_snapshot(&root, &name) {
|
||||||
Ok(_) => Json(serde_json::json!({"success": true, "name": name})),
|
Ok(_) => Json(serde_json::json!({"success": true, "name": name})),
|
||||||
Err(e) => Json(serde_json::json!({"success": false, "error": e.to_string()})),
|
Err(e) => Json(serde_json::json!({"success": false, "error": e.to_string()})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_storage_stats_handler() -> Json<StorageStatsResponse> {
|
async fn get_storage_stats_handler(Query(params): Query<std::collections::HashMap<String, String>>) -> Json<StorageStatsResponse> {
|
||||||
|
let root = params.get("root").map(|p| PathBuf::from(p)).unwrap_or_else(|| PathBuf::from("/data"));
|
||||||
let backend = LocalFs::new();
|
let backend = LocalFs::new();
|
||||||
let root = PathBuf::from("/data");
|
|
||||||
match backend.stat(&root) {
|
match backend.stat(&root) {
|
||||||
Ok(stat) => Json(StorageStatsResponse {
|
Ok(stat) => Json(StorageStatsResponse {
|
||||||
total_size: stat.size,
|
total_size: stat.size,
|
||||||
|
|||||||
Reference in New Issue
Block a user