diff options
author | Toby Vincent <tobyv13@gmail.com> | 2022-05-11 20:41:03 -0500 |
---|---|---|
committer | Toby Vincent <tobyv13@gmail.com> | 2022-05-11 20:41:03 -0500 |
commit | 03675f76b53abd63ea99e9e4af614d73615a496b (patch) | |
tree | a07ecc37b62db3147c971e12dced2cc5c8727de5 /zone_overlay/src/overlay.rs | |
parent | bd0793b71f557049f252e0256297e0407c065bad (diff) |
feat: create Volumes impl for overlay file system
Diffstat (limited to 'zone_overlay/src/overlay.rs')
-rw-r--r-- | zone_overlay/src/overlay.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/zone_overlay/src/overlay.rs b/zone_overlay/src/overlay.rs new file mode 100644 index 0000000..5f2cf58 --- /dev/null +++ b/zone_overlay/src/overlay.rs @@ -0,0 +1,87 @@ +use fs_extra::dir; +use std::path::PathBuf; +use walkdir::WalkDir; +use zone_core::{Container, Templates, Volumes}; + +use crate::{ + error::{TemplateError, VolumeError}, + Config, Error, +}; + +#[derive(Default, Debug)] +pub struct Overlay { + pub config: Config, +} + +impl Volumes for Overlay { + type Error = Error; + + fn list_volumes(&self) -> Result<Vec<Container>, Self::Error> { + if !&self.config.volumes.is_dir() { + return Err(VolumeError::BasePath.into()); + } + + let containers = WalkDir::new(&self.config.volumes) + .max_depth(2) + .into_iter() + .filter_entry(|entry| entry.file_type().is_dir() && entry.depth() == 2) + .filter_map(|res| res.map(|entry| entry.into_path()).ok()) + .filter_map( + |path_buf| match path_buf.strip_prefix(&self.config.volumes) { + Ok(p) => Container::try_from(PathBuf::from(p)).ok(), + Err(_) => None, + }, + ) + .collect(); + + Ok(containers) + } + + fn get_volume(&self, container: &Container) -> Result<PathBuf, Self::Error> { + match self + .config + .volumes + .join(PathBuf::from(container.to_owned())) + { + path if path.is_dir() => Ok(path), + _ => Err(VolumeError::NotFound.into()), + } + } +} + +impl Templates for Overlay { + type Error = Error; + + fn list_templates(&self) -> Result<Vec<String>, Self::Error> { + let templates = std::fs::read_dir(&self.config.templates) + .map_err(TemplateError::BasePath)? + .into_iter() + .filter_map(|e| match e { + Ok(e) if e.path().is_dir() => e.file_name().to_str().map(String::from), + _ => None, + }) + .collect(); + + Ok(templates) + } + + fn clone_from(&self, template: String, owner: String) -> Result<Container, Self::Error> { + let container = Container { + id: self.get_last_id(&template, &owner)?, + template, + owner, + }; + + let to = &self + .config + .volumes + .join(PathBuf::from(container.to_owned())); + + let from = &self.config.templates.join(&container.template); + + dir::copy(from, to, &Default::default()) + .map(|_| container) + .map_err(TemplateError::from) + .map_err(Error::from) + } +} |