diff options
author | Toby Vincent <tobyv13@gmail.com> | 2022-05-06 14:27:17 -0500 |
---|---|---|
committer | Toby Vincent <tobyv13@gmail.com> | 2022-05-06 14:27:17 -0500 |
commit | cdb45e032b078156eddbd47cb350c6ae66a64098 (patch) | |
tree | 796dc0597c410d23053e72e0af9d23a6cb26313e /zone_core/src/container.rs | |
parent | 730305eb1a6f9615dccb9bd94b1c371bba003615 (diff) |
refactor: generalize zfs impl into storage traits
Diffstat (limited to 'zone_core/src/container.rs')
-rw-r--r-- | zone_core/src/container.rs | 125 |
1 files changed, 62 insertions, 63 deletions
diff --git a/zone_core/src/container.rs b/zone_core/src/container.rs index 71dfb73..db7458e 100644 --- a/zone_core/src/container.rs +++ b/zone_core/src/container.rs @@ -1,57 +1,92 @@ use clap::Args; -use derive_builder::Builder; use serde::{Deserialize, Serialize}; -use std::{fmt::Display, path::PathBuf}; +use std::{ffi::OsStr, fmt::Display, path::PathBuf}; use tabled::Tabled; use crate::FilterContainer; -pub use status::ContainerStatus; +pub use self::error::ParsingError; +pub use self::status::Status; +mod error; mod status; -#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Builder, Tabled, Clone, Args)] -#[builder( - name = "ContainerOptions", - derive(Debug, Serialize, Deserialize), - field(public) -)] +#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Tabled, Clone, Args)] #[serde(rename_all = "camelCase")] pub struct Container { #[tabled("ID")] - pub id: u64, + pub id: u32, #[tabled("Template")] - pub parent: String, + pub template: String, #[tabled("User")] - pub user: String, -} - -impl Container { - pub fn builder() -> ContainerOptions { - ContainerOptions::default() - } + pub owner: String, } impl Display for Container { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}-{}-{}", self.user, self.parent, self.id) + write!(f, "{}-{}-{}", self.template, self.owner, self.id) } } impl From<Container> for String { fn from(c: Container) -> Self { - format!("{}-{}-{}", c.user, c.parent, c.id) + format!("{}-{}-{}", c.template, c.owner, c.id) } } +impl From<Container> for PathBuf { + fn from(c: Container) -> Self { + PathBuf::from(format!("{}/{}/{}", c.template, c.owner, c.id)) + } +} + +impl TryFrom<String> for Container { + type Error = ParsingError; + + fn try_from(s: String) -> Result<Self, Self::Error> { + let v = s.split('-').collect::<Vec<_>>(); + match v[v.len() - 3..] { + [i, o, t] => Ok(Container { + id: i.parse()?, + owner: o.into(), + template: t.into(), + }), + _ => Err(s).map_err(ParsingError::from), + } + } +} + +impl TryFrom<PathBuf> for Container { + type Error = ParsingError; + + fn try_from(p: PathBuf) -> Result<Self, Self::Error> { + let v = p.iter().map(OsStr::to_str).collect::<Vec<_>>(); + match v[v.len() - 3..] { + [Some(i), Some(o), Some(t)] => Ok(Container { + id: i.parse()?, + owner: o.into(), + template: t.into(), + }), + _ => Err(p).map_err(ParsingError::from), + } + } +} + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct ContainerOptions { + pub id: Option<u32>, + pub parent: Option<String>, + pub owner: Option<String>, +} + impl From<Container> for ContainerOptions { fn from(c: Container) -> Self { Self { id: Some(c.id), - parent: Some(c.parent), - user: Some(c.user), + parent: Some(c.template), + owner: Some(c.owner), } } } @@ -60,8 +95,8 @@ impl From<&Container> for &ContainerOptions { fn from(c: &Container) -> Self { ContainerOptions { id: Some(c.id.to_owned()), - parent: Some(c.parent.to_owned()), - user: Some(c.user.to_owned()), + parent: Some(c.template.to_owned()), + owner: Some(c.owner.to_owned()), } .into() } @@ -76,7 +111,7 @@ impl From<ContainerOptions> for &ContainerOptions { #[derive(Debug, Serialize, Deserialize, Clone, Args)] pub struct CloneOptions { pub template: String, - pub user: String, + pub owner: String, } impl<T> FilterContainer for T @@ -88,45 +123,9 @@ where self.filter_map(|c| -> Option<Container> { c.try_into().ok() }) .filter(|c| { pred.id.map_or(false, |p| p == c.id) - && pred.parent.as_ref().map_or(false, |p| p == &c.parent) - && pred.user.as_ref().map_or(false, |p| p == &c.user) + && pred.parent.as_ref().map_or(false, |p| p == &c.template) + && pred.owner.as_ref().map_or(false, |p| p == &c.owner) }) .collect() } } - -impl TryFrom<zone_zfs::FileSystem> for Container { - type Error = zone_zfs::Error; - - fn try_from(fs: zone_zfs::FileSystem) -> zone_zfs::Result<Self> { - let path_buf = PathBuf::from(fs.dataset()) - .file_name() - .ok_or_else(|| { - zone_zfs::Error::FileSystem(format!("Invalid FileSystem path: {:?}", fs)) - })? - .to_string_lossy() - .into_owned(); - - let (user, id) = path_buf.rsplit_once('-').ok_or_else(|| { - zone_zfs::Error::FileSystem(format!("Invalid FileSystem name: {:?}", fs)) - })?; - - let id = id.parse::<u64>().map_err(|err| { - zone_zfs::Error::FileSystem(format!("Failed to parse container ID: {:?}", err)) - })?; - - let template = PathBuf::from(fs.dataset()) - .parent() - .ok_or_else(|| { - zone_zfs::Error::FileSystem(format!("Invalid path for filesystem: {:?}", &fs)) - })? - .to_string_lossy() - .into_owned(); - - Ok(Container { - id, - parent: template, - user: user.to_string(), - }) - } -} |