aboutsummaryrefslogtreecommitdiffstats
path: root/zone_zfs/src
diff options
context:
space:
mode:
authorToby Vincent <tobyv13@gmail.com>2022-02-13 21:14:33 -0600
committerToby Vincent <tobyv13@gmail.com>2022-02-13 21:14:33 -0600
commit8985b2ffd7c8d6e9cf726f630f39ce6e8f00df79 (patch)
tree3e632e691378e36d389393d80049fa81c1b8f9cf /zone_zfs/src
parent96e571eca2991a19fc9bcdc26e451c4fad5bc791 (diff)
refactor: add error handling to libraries
refactor libraries from using anyhow to explicitly handling errors
Diffstat (limited to 'zone_zfs/src')
-rw-r--r--zone_zfs/src/file_system.rs73
-rw-r--r--zone_zfs/src/lib.rs62
-rw-r--r--zone_zfs/src/snapshot.rs25
3 files changed, 82 insertions, 78 deletions
diff --git a/zone_zfs/src/file_system.rs b/zone_zfs/src/file_system.rs
index 50e3c56..83164c9 100644
--- a/zone_zfs/src/file_system.rs
+++ b/zone_zfs/src/file_system.rs
@@ -1,12 +1,11 @@
-use anyhow::{anyhow, Context, Result};
use std::{
ffi::{OsStr, OsString},
fmt::Display,
path::PathBuf,
- process::{Command, Output},
+ process::Command,
};
-use super::snapshot::Snapshot;
+use crate::{snapshot::Snapshot, Error, Result};
#[derive(Debug)]
pub struct FileSystem {
@@ -22,9 +21,9 @@ impl Display for FileSystem {
// pool/000.0/nkollack-1
impl TryFrom<OsString> for FileSystem {
- type Error = anyhow::Error;
+ type Error = Error;
- fn try_from(value: OsString) -> Result<Self, Self::Error> {
+ fn try_from(value: OsString) -> Result<Self> {
Ok(FileSystem {
value,
mountpoint: None,
@@ -33,9 +32,9 @@ impl TryFrom<OsString> for FileSystem {
}
impl TryFrom<&str> for FileSystem {
- type Error = anyhow::Error;
+ type Error = Error;
- fn try_from(value: &str) -> Result<Self, Self::Error> {
+ fn try_from(value: &str) -> Result<Self> {
value.try_into()
}
}
@@ -58,34 +57,24 @@ impl From<FileSystem> for String {
}
}
-impl TryFrom<Output> for FileSystem {
- type Error = anyhow::Error;
-
- fn try_from(value: Output) -> Result<Self, Self::Error> {
- std::str::from_utf8(&value.stdout)?.try_into()
- }
-}
-
impl FileSystem {
pub(super) fn get_name(&self) -> Result<String> {
Ok(PathBuf::from(self.value.clone())
.file_name()
- .context("Invalid path for filesystem")?
+ .ok_or_else(|| Error::FileSystem(format!("Invalid path for filesystem: {:?}", self)))?
.to_string_lossy()
.into_owned())
}
pub(super) fn set_quota(&self, quota: &str) -> Result<()> {
- match Command::new("zfs")
+ Command::new("zfs")
.arg("set")
.arg(format!("quota={}", quota))
.arg(&self.value)
.status()?
.success()
- {
- true => Ok(()),
- false => Err(anyhow!("Failed to set a quota: {:?}", self)),
- }
+ .then(|| ())
+ .ok_or_else(|| Error::FileSystem(format!("Failed to set quota: {:?}", self)))
}
pub(super) fn get_snapshots(&self) -> Result<Vec<Snapshot>> {
@@ -100,7 +89,8 @@ impl FileSystem {
.output()?
.stdout;
- String::from_utf8(stdout)?
+ String::from_utf8(stdout)
+ .map_err(|err| Error::FileSystem(format!("Failed to parse command output: {:?}", err)))?
.split_whitespace()
.map(|s| s.try_into())
.collect()
@@ -115,7 +105,7 @@ impl FileSystem {
}
pub(super) fn get_file_systems() -> Result<Vec<FileSystem>> {
- let output = Command::new("zfs")
+ let stdout = Command::new("zfs")
.arg("list")
.arg("-H")
.arg("-o")
@@ -123,34 +113,31 @@ impl FileSystem {
.output()?
.stdout;
- std::str::from_utf8(&output)?
+ String::from_utf8(stdout)
+ .map_err(|err| Error::FileSystem(format!("Failed to parse command output: {:?}", err)))?
.split_whitespace()
- .map(|fs| fs.try_into())
+ .map(|s| s.try_into())
.collect()
}
pub fn mount(&self) -> Result<()> {
- match Command::new("zfs")
+ Command::new("zfs")
.arg("mount")
.arg(&self.value)
.status()?
.success()
- {
- true => Ok(()),
- false => Err(anyhow!("Failed to mount the filesystem: {:?}", self)),
- }
+ .then(|| ())
+ .ok_or_else(|| Error::FileSystem(format!("Failed to mount: {:?}", self)))
}
pub fn unmount(&self) -> Result<()> {
- match Command::new("zfs")
+ Command::new("zfs")
.arg("unmount")
.arg(&self.value)
.status()?
.success()
- {
- true => Ok(()),
- false => Err(anyhow!("Failed to unmount the filesystem: {:?}", self)),
- }
+ .then(|| ())
+ .ok_or_else(|| Error::FileSystem(format!("Failed to unmount: {:?}", self)))
}
pub fn destroy(&self, force: bool) -> Result<()> {
@@ -161,14 +148,12 @@ impl FileSystem {
}
args.push(&self.value);
- match Command::new("zfs")
- .arg("destroy")
- .args(args)
- .status()?
- .success()
- {
- true => Ok(()),
- false => Err(anyhow!("Failed to destroy the filesystem: {:?}", self)),
- }
+ Command::new("zfs")
+ .arg("destroy")
+ .args(args)
+ .status()?
+ .success()
+ .then(|| ())
+ .ok_or_else(|| Error::FileSystem(format!("Failed to destroy: {:?}", self)))
}
}
diff --git a/zone_zfs/src/lib.rs b/zone_zfs/src/lib.rs
index 53947a6..c430cba 100644
--- a/zone_zfs/src/lib.rs
+++ b/zone_zfs/src/lib.rs
@@ -1,13 +1,32 @@
use self::file_system::FileSystem;
-use anyhow::Result;
-use figment::{providers::{Serialized, Toml, Env, Format}, Figment, Metadata, Profile, Provider};
+use figment::{
+ providers::{Env, Format, Serialized, Toml},
+ Figment, Metadata, Profile, Provider,
+};
use serde::{Deserialize, Serialize};
-use std::path::PathBuf;
+use std::{io, path::PathBuf, result};
pub mod file_system;
pub mod snapshot;
+type Result<T> = result::Result<T, Error>;
+
+#[derive(thiserror::Error, Debug)]
+pub enum Error {
+ #[error("ZFS error")]
+ ZFS(String),
+
+ #[error("Snapshot Error: {0:?}")]
+ Snapshot(String),
+
+ #[error("File System Error: {0:?}")]
+ FileSystem(String),
+
+ #[error("IO Error: Failed to run command")]
+ IO(#[from] io::Error),
+}
+
#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
pub quota: String,
@@ -22,11 +41,10 @@ impl Default for Config {
}
impl Config {
- pub fn from<T: Provider>(provider: T) -> Result<Config, figment::Error> {
+ pub fn from<T: Provider>(provider: T) -> result::Result<Config, figment::Error> {
Figment::from(provider).extract()
}
- // Provide a default provider, a `Figment`.
pub fn figment() -> Figment {
Figment::from(Config::default())
.merge(Toml::file(Env::var_or("ZFS_CONFIG", "ZFS.toml")).nested())
@@ -39,7 +57,9 @@ impl Provider for Config {
Metadata::named("ZFS Config")
}
- fn data(&self) -> Result<figment::value::Map<Profile, figment::value::Dict>, figment::Error> {
+ fn data(
+ &self,
+ ) -> result::Result<figment::value::Map<Profile, figment::value::Dict>, figment::Error> {
Serialized::defaults(Config::default()).data()
}
}
@@ -49,33 +69,27 @@ pub fn create_file_system(
name: String,
config: &Config,
) -> Result<FileSystem> {
- let fs = FileSystem::get_file_systems()
- .unwrap()
+ let fs = FileSystem::get_file_systems()?
.into_iter()
- .find(|fs| match fs.get_name() {
- Ok(name) => name == base_fs_name,
- Err(_) => false,
+ .find_map(|fs| match fs.get_name() {
+ Ok(n) if n == base_fs_name => Some(fs),
+ _ => None,
})
- .unwrap_or_else(|| todo!("Handle!"));
+ .ok_or_else(|| Error::FileSystem("No ".to_string()))?;
let snapshot = fs
- .get_latest_snapshot()
- .expect("No snapshot found")
- .unwrap();
+ .get_latest_snapshot()?
+ .ok_or_else(|| Error::Snapshot("No snapshot found".to_string()))?;
let mut mountpoint = fs.value;
mountpoint.push(name);
- let cloned_fs = snapshot
- .clone_into_file_system(
- snapshot.file_system.get_name()?,
- Some(PathBuf::from(mountpoint)),
- )
- .unwrap();
+ let cloned_fs = snapshot.clone_into_file_system(
+ snapshot.file_system.get_name()?,
+ Some(PathBuf::from(mountpoint)),
+ )?;
- cloned_fs
- .set_quota(&config.quota)
- .expect("Failed to set quota");
+ cloned_fs.set_quota(&config.quota)?;
Ok(cloned_fs)
}
diff --git a/zone_zfs/src/snapshot.rs b/zone_zfs/src/snapshot.rs
index 48faa68..14fafb4 100644
--- a/zone_zfs/src/snapshot.rs
+++ b/zone_zfs/src/snapshot.rs
@@ -1,11 +1,10 @@
-use anyhow::{anyhow, Result};
use chrono::{DateTime, Utc};
use std::{ffi::OsString, path::PathBuf, process::Command};
use tracing::warn;
-use super::file_system::FileSystem;
+use crate::{file_system::FileSystem, Error, Result};
-#[derive()]
+#[derive(Debug)]
pub struct Snapshot {
// pool/000.0@00000000000
pub value: OsString,
@@ -15,9 +14,9 @@ pub struct Snapshot {
impl TryFrom<&str> for Snapshot {
// <file_system>@<timestamp>
- type Error = anyhow::Error;
+ type Error = Error;
- fn try_from(value: &str) -> Result<Self, Self::Error> {
+ fn try_from(value: &str) -> Result<Self> {
match value.split('@').collect::<Vec<&str>>()[..] {
[file_system, name] => Ok(Snapshot {
file_system: FileSystem::try_from(file_system)?,
@@ -30,7 +29,10 @@ impl TryFrom<&str> for Snapshot {
chrono::MIN_DATETIME
}),
}),
- _ => Err(anyhow!("Failed to parse snapshot: {}", value)),
+ _ => Err(Error::Snapshot(format!(
+ "Failed to parse snapshot: {:?}",
+ value
+ ))),
}
}
}
@@ -56,9 +58,12 @@ impl Snapshot {
.arg(format!("mountpoint={}", mp.to_string_lossy()));
};
- match command.arg(&self.value).arg(&new_fs).status()?.success() {
- true => Ok(new_fs),
- false => Err(anyhow!("Failed to clone snapshot: {:?}", new_fs)),
- }
+ command
+ .arg(&self.value)
+ .arg(&new_fs)
+ .status()?
+ .success()
+ .then(|| new_fs)
+ .ok_or_else(|| Error::Snapshot(format!("Failed to clone snapshot: {:?}", self)))
}
}