merge: restore.rs
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
use crate::zfs::ZfsOps;
|
||||||
|
use anyhow::Result;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub fn find_snapshot(zfs: &dyn ZfsOps, dataset: &str, tag: &str) -> Result<Option<String>> {
|
||||||
|
let full = format!("{}@{}", dataset, tag);
|
||||||
|
let snaps = zfs.list_snapshots(dataset)?;
|
||||||
|
Ok(snaps.into_iter().find(|s| *s == full))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restore_project(
|
||||||
|
zfs: &dyn ZfsOps,
|
||||||
|
project_name: &str,
|
||||||
|
snapshot_full_name: &str,
|
||||||
|
warm_dataset: &str,
|
||||||
|
) -> Result<PathBuf> {
|
||||||
|
let ts = snapshot_full_name.split('@').nth(1).unwrap_or("restore");
|
||||||
|
let dest_dataset = format!("{}/{}-restore-{}", warm_dataset, project_name, ts);
|
||||||
|
zfs.clone_snapshot(snapshot_full_name, &dest_dataset)?;
|
||||||
|
let mount_path = format!("/{}", dest_dataset.replace('/', "/"));
|
||||||
|
Ok(PathBuf::from(mount_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::zfs::MockZfs;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_restore_clones_snapshot() {
|
||||||
|
let zfs = MockZfs::default();
|
||||||
|
zfs.snapshot("slab/projects", "hourly-2026-06-16-0300").unwrap();
|
||||||
|
|
||||||
|
let dest = restore_project(
|
||||||
|
&zfs,
|
||||||
|
"kitchen-cash",
|
||||||
|
"slab/projects@hourly-2026-06-16-0300",
|
||||||
|
"slab/projects",
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
assert!(dest.to_string_lossy().contains("kitchen-cash-restore"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_restore_errors_on_missing_snapshot() {
|
||||||
|
let zfs = MockZfs::default();
|
||||||
|
let result = find_snapshot(
|
||||||
|
&zfs,
|
||||||
|
"slab/projects",
|
||||||
|
"nonexistent-snap",
|
||||||
|
);
|
||||||
|
assert!(result.unwrap().is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user