From cdb45e032b078156eddbd47cb350c6ae66a64098 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Fri, 6 May 2022 14:27:17 -0500 Subject: refactor: generalize zfs impl into storage traits --- zone_core/src/container.rs | 125 ++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 63 deletions(-) (limited to 'zone_core/src/container.rs') 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 for String { fn from(c: Container) -> Self { - format!("{}-{}-{}", c.user, c.parent, c.id) + format!("{}-{}-{}", c.template, c.owner, c.id) } } +impl From for PathBuf { + fn from(c: Container) -> Self { + PathBuf::from(format!("{}/{}/{}", c.template, c.owner, c.id)) + } +} + +impl TryFrom for Container { + type Error = ParsingError; + + fn try_from(s: String) -> Result { + let v = s.split('-').collect::>(); + 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 for Container { + type Error = ParsingError; + + fn try_from(p: PathBuf) -> Result { + let v = p.iter().map(OsStr::to_str).collect::>(); + 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, + pub parent: Option, + pub owner: Option, +} + impl From 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 for &ContainerOptions { #[derive(Debug, Serialize, Deserialize, Clone, Args)] pub struct CloneOptions { pub template: String, - pub user: String, + pub owner: String, } impl FilterContainer for T @@ -88,45 +123,9 @@ where self.filter_map(|c| -> Option { 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 for Container { - type Error = zone_zfs::Error; - - fn try_from(fs: zone_zfs::FileSystem) -> zone_zfs::Result { - 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::().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(), - }) - } -} -- cgit v1.2.3-70-g09d2