aboutsummaryrefslogtreecommitdiffstats
path: root/zone_overlay/src/overlay.rs
diff options
context:
space:
mode:
authorToby Vincent <tobyv13@gmail.com>2022-05-11 20:41:03 -0500
committerToby Vincent <tobyv13@gmail.com>2022-05-11 20:41:03 -0500
commit03675f76b53abd63ea99e9e4af614d73615a496b (patch)
treea07ecc37b62db3147c971e12dced2cc5c8727de5 /zone_overlay/src/overlay.rs
parentbd0793b71f557049f252e0256297e0407c065bad (diff)
feat: create Volumes impl for overlay file system
Diffstat (limited to 'zone_overlay/src/overlay.rs')
-rw-r--r--zone_overlay/src/overlay.rs87
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)
+ }
+}