aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock10
-rw-r--r--zone_core/src/lib.rs10
-rw-r--r--zone_zfs/Cargo.toml3
-rw-r--r--zone_zfs/src/config.rs48
-rw-r--r--zone_zfs/src/error.rs20
-rw-r--r--zone_zfs/src/file_system.rs84
-rw-r--r--zone_zfs/src/lib.rs105
-rw-r--r--zone_zfs/src/snapshot.rs29
-rw-r--r--zone_zfs/src/zfs.rs60
-rw-r--r--zoned/src/api.rs35
-rw-r--r--zoned/src/config.rs8
-rw-r--r--zoned/src/error.rs52
-rw-r--r--zoned/src/lib.rs62
-rw-r--r--zoned/src/main.rs11
14 files changed, 308 insertions, 229 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ba83684..1e39d3d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -112,6 +112,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
+name = "bytesize"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2165,6 +2174,7 @@ dependencies = [
name = "zone_zfs"
version = "0.1.0"
dependencies = [
+ "bytesize",
"chrono",
"figment",
"serde",
diff --git a/zone_core/src/lib.rs b/zone_core/src/lib.rs
index 25fe33a..6801ee8 100644
--- a/zone_core/src/lib.rs
+++ b/zone_core/src/lib.rs
@@ -76,7 +76,7 @@ impl<'r> Responder<'r, 'static> for Container {
}
impl TryFrom<FileSystem> for Container {
- type Error = zone_zfs::Error;
+ type Error = zone_zfs::error::Error;
fn try_from(file_system: FileSystem) -> Result<Self, Self::Error> {
let path_buf = PathBuf::from(&file_system)
@@ -116,11 +116,13 @@ impl TryFrom<zone_nspawn::Container> for Container {
type Error = zone_nspawn::Error;
fn try_from(value: zone_nspawn::Container) -> Result<Self, Self::Error> {
- // id, template, user
- let v: Vec<&str> = value.machine.split("-").collect();
+ // id, template, user
+ let v: Vec<&str> = value.machine.split('-').collect();
Ok(Container {
- id: v[0].parse().map_err(|err| Self::Error::Parsing(format!("Failed to parse container id: {:?}", err)))?,
+ id: v[0].parse().map_err(|err| {
+ Self::Error::Parsing(format!("Failed to parse container id: {:?}", err))
+ })?,
template: v[1].to_owned(),
user: v[2].to_owned(),
status: ContainerStatus::Running,
diff --git a/zone_zfs/Cargo.toml b/zone_zfs/Cargo.toml
index 472dda1..41ef655 100644
--- a/zone_zfs/Cargo.toml
+++ b/zone_zfs/Cargo.toml
@@ -5,8 +5,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+bytesize = { version = "1.1.0", features = ["serde"] }
chrono = "0.4.19"
figment = "0.10.6"
serde = "1.0.136"
thiserror = "1.0.30"
tracing = "0.1.29"
+
+[features]
diff --git a/zone_zfs/src/config.rs b/zone_zfs/src/config.rs
new file mode 100644
index 0000000..f3dc390
--- /dev/null
+++ b/zone_zfs/src/config.rs
@@ -0,0 +1,48 @@
+use bytesize::ByteSize;
+use figment::{
+ error::Result,
+ providers::{Env, Format, Serialized, Toml},
+ value::{Dict, Map},
+ Figment, Metadata, Profile, Provider,
+};
+use serde::{Deserialize, Serialize};
+use std::path::PathBuf;
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct Config {
+ pub quota: ByteSize,
+ pub pool_name: String,
+ pub mountpoint: PathBuf,
+}
+
+impl Default for Config {
+ fn default() -> Self {
+ Config {
+ quota: ByteSize::gb(16),
+ pool_name: String::from("pool"),
+ mountpoint: PathBuf::from("/svr"),
+ }
+ }
+}
+
+impl Config {
+ pub fn from<T: Provider>(provider: T) -> Result<Config> {
+ Figment::from(provider).extract()
+ }
+
+ pub fn figment() -> Figment {
+ Figment::from(Config::default())
+ .merge(Toml::file(Env::var_or("ZFS_CONFIG", "ZFS.toml")).nested())
+ .merge(Env::prefixed("ZFS_").global())
+ }
+}
+
+impl Provider for Config {
+ fn metadata(&self) -> Metadata {
+ Metadata::named("ZFS Config")
+ }
+
+ fn data(&self) -> Result<Map<Profile, Dict>> {
+ Serialized::defaults(Config::default()).data()
+ }
+}
diff --git a/zone_zfs/src/error.rs b/zone_zfs/src/error.rs
new file mode 100644
index 0000000..0275384
--- /dev/null
+++ b/zone_zfs/src/error.rs
@@ -0,0 +1,20 @@
+pub type Result<T> = std::result::Result<T, Error>;
+
+#[allow(clippy::large_enum_variant)]
+#[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] std::io::Error),
+
+ #[error("Config Error: {0:?}")]
+ Config(#[from] figment::Error),
+}
diff --git a/zone_zfs/src/file_system.rs b/zone_zfs/src/file_system.rs
index 83164c9..6bee10b 100644
--- a/zone_zfs/src/file_system.rs
+++ b/zone_zfs/src/file_system.rs
@@ -1,3 +1,8 @@
+use crate::{
+ error::{Error, Result},
+ snapshot::Snapshot,
+};
+use bytesize::ByteSize;
use std::{
ffi::{OsStr, OsString},
fmt::Display,
@@ -5,12 +10,21 @@ use std::{
process::Command,
};
-use crate::{snapshot::Snapshot, Error, Result};
-
-#[derive(Debug)]
+macro_rules! opt [
+ ($name:expr, $value:expr) => ({
+ let mut _temp = OsString::new();
+ _temp.push($name);
+ _temp.push("=");
+ _temp.push($value);
+ _temp
+ })
+];
+
+#[derive(Debug, Default, Clone)]
pub struct FileSystem {
pub(crate) value: OsString,
- pub(crate) mountpoint: Option<PathBuf>,
+ pub(crate) mountpoint: PathBuf,
+ pub(crate) quota: ByteSize,
}
impl Display for FileSystem {
@@ -19,14 +33,13 @@ impl Display for FileSystem {
}
}
-// pool/000.0/nkollack-1
impl TryFrom<OsString> for FileSystem {
type Error = Error;
fn try_from(value: OsString) -> Result<Self> {
Ok(FileSystem {
value,
- mountpoint: None,
+ ..FileSystem::default()
})
}
}
@@ -59,26 +72,43 @@ impl From<FileSystem> for String {
impl FileSystem {
pub(super) fn get_name(&self) -> Result<String> {
- Ok(PathBuf::from(self.value.clone())
+ PathBuf::from(&self.value)
.file_name()
- .ok_or_else(|| Error::FileSystem(format!("Invalid path for filesystem: {:?}", self)))?
- .to_string_lossy()
- .into_owned())
+ .ok_or_else(|| Error::FileSystem(format!("Invalid path for filesystem: {:?}", self)))
+ .map(|s| s.to_string_lossy().into_owned())
}
- pub(super) fn set_quota(&self, quota: &str) -> Result<()> {
+ pub(super) fn set_opt<T, U>(&self, name: T, value: U) -> Result<&Self>
+ where
+ T: AsRef<OsStr>,
+ U: AsRef<OsStr>,
+ {
Command::new("zfs")
.arg("set")
- .arg(format!("quota={}", quota))
+ .arg(opt!(&name, value))
.arg(&self.value)
.status()?
.success()
- .then(|| ())
- .ok_or_else(|| Error::FileSystem(format!("Failed to set quota: {:?}", self)))
+ .then(|| self)
+ .ok_or_else(|| {
+ Error::FileSystem(format!("Failed to set {:?}: {:?}", name.as_ref(), self))
+ })
+ }
+
+ pub(super) fn set_quota(&mut self, quota: ByteSize) -> Result<Self> {
+ self.set_opt("quota", quota.to_string())?;
+ self.quota = quota;
+ Ok(self.to_owned())
+ }
+
+ pub(super) fn set_mountpoint(&mut self, mountpoint: PathBuf) -> Result<Self> {
+ self.set_opt("mountpoint", &mountpoint)?;
+ self.mountpoint = mountpoint;
+ Ok(self.to_owned())
}
pub(super) fn get_snapshots(&self) -> Result<Vec<Snapshot>> {
- let stdout = Command::new("zfs")
+ Command::new("zfs")
.arg("list")
.arg("-H")
.arg("-o")
@@ -86,13 +116,11 @@ impl FileSystem {
.arg("-t")
.arg("snapshot")
.arg(self)
- .output()?
- .stdout;
-
- String::from_utf8(stdout)
+ .output()
+ .map(|o| String::from_utf8(o.stdout))?
.map_err(|err| Error::FileSystem(format!("Failed to parse command output: {:?}", err)))?
.split_whitespace()
- .map(|s| s.try_into())
+ .map(Snapshot::try_from)
.collect()
}
@@ -104,22 +132,6 @@ impl FileSystem {
.max_by_key(|s| s.timestamp))
}
- pub(super) fn get_file_systems() -> Result<Vec<FileSystem>> {
- let stdout = Command::new("zfs")
- .arg("list")
- .arg("-H")
- .arg("-o")
- .arg("name")
- .output()?
- .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()
- }
-
pub fn mount(&self) -> Result<()> {
Command::new("zfs")
.arg("mount")
diff --git a/zone_zfs/src/lib.rs b/zone_zfs/src/lib.rs
index c430cba..7c50861 100644
--- a/zone_zfs/src/lib.rs
+++ b/zone_zfs/src/lib.rs
@@ -1,104 +1,19 @@
-use self::file_system::FileSystem;
-use figment::{
- providers::{Env, Format, Serialized, Toml},
- Figment, Metadata, Profile, Provider,
-};
-use serde::{Deserialize, Serialize};
-use std::{io, path::PathBuf, result};
+pub use zfs::ZFS;
+pub use error::{Error, Result};
+pub use file_system::FileSystem;
+pub use config::Config;
+pub mod config;
+pub mod error;
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,
-}
-
-impl Default for Config {
- fn default() -> Self {
- Config {
- quota: "16G".to_string(),
- }
- }
-}
-
-impl Config {
- pub fn from<T: Provider>(provider: T) -> result::Result<Config, figment::Error> {
- Figment::from(provider).extract()
- }
-
- pub fn figment() -> Figment {
- Figment::from(Config::default())
- .merge(Toml::file(Env::var_or("ZFS_CONFIG", "ZFS.toml")).nested())
- .merge(Env::prefixed("ZFS_").global())
- }
-}
-
-impl Provider for Config {
- fn metadata(&self) -> Metadata {
- Metadata::named("ZFS Config")
- }
-
- fn data(
- &self,
- ) -> result::Result<figment::value::Map<Profile, figment::value::Dict>, figment::Error> {
- Serialized::defaults(Config::default()).data()
- }
-}
-
-pub fn create_file_system(
- base_fs_name: String,
- name: String,
- config: &Config,
-) -> Result<FileSystem> {
- let fs = FileSystem::get_file_systems()?
- .into_iter()
- .find_map(|fs| match fs.get_name() {
- Ok(n) if n == base_fs_name => Some(fs),
- _ => None,
- })
- .ok_or_else(|| Error::FileSystem("No ".to_string()))?;
-
- let snapshot = fs
- .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)),
- )?;
-
- cloned_fs.set_quota(&config.quota)?;
-
- Ok(cloned_fs)
-}
+pub mod zfs;
#[cfg(test)]
mod tests {
#[test]
- fn zfs_list() {
- use super::*;
- assert!(FileSystem::get_file_systems().is_ok());
+ fn it_works() {
+ let result = 2 + 2;
+ assert_eq!(result, 4);
}
}
diff --git a/zone_zfs/src/snapshot.rs b/zone_zfs/src/snapshot.rs
index 14fafb4..b0fabb9 100644
--- a/zone_zfs/src/snapshot.rs
+++ b/zone_zfs/src/snapshot.rs
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
use std::{ffi::OsString, path::PathBuf, process::Command};
use tracing::warn;
-use crate::{file_system::FileSystem, Error, Result};
+use crate::{error::Error, error::Result, file_system::FileSystem, Config};
#[derive(Debug)]
pub struct Snapshot {
@@ -38,32 +38,17 @@ impl TryFrom<&str> for Snapshot {
}
impl Snapshot {
- pub fn clone_into_file_system(
- &self,
- name: String,
- mountpoint: Option<PathBuf>,
- ) -> Result<FileSystem> {
- let new_fs = FileSystem {
- value: PathBuf::from(&self.file_system.value).join(name).into(),
- mountpoint,
- };
+ pub fn clone_into_file_system(&self, new_fs: PathBuf) -> Result<FileSystem> {
+ let mut file_system = self.file_system.clone();
+ file_system.value.push(&new_fs);
- let mut command = Command::new("zfs");
-
- command.arg("clone");
-
- if let Some(mp) = &new_fs.mountpoint {
- command
- .arg("-o")
- .arg(format!("mountpoint={}", mp.to_string_lossy()));
- };
-
- command
+ Command::new("zfs")
+ .arg("clone")
.arg(&self.value)
.arg(&new_fs)
.status()?
.success()
- .then(|| new_fs)
+ .then(|| file_system)
.ok_or_else(|| Error::Snapshot(format!("Failed to clone snapshot: {:?}", self)))
}
}
diff --git a/zone_zfs/src/zfs.rs b/zone_zfs/src/zfs.rs
new file mode 100644
index 0000000..7f34951
--- /dev/null
+++ b/zone_zfs/src/zfs.rs
@@ -0,0 +1,60 @@
+use figment::{Figment, Provider};
+use std::path::PathBuf;
+use std::process::Command;
+
+use crate::{Config, Error, FileSystem, Result};
+
+#[derive(Default, Debug)]
+pub struct ZFS {
+ pub config: Config,
+}
+
+impl ZFS {
+ pub fn new() -> Result<Self> {
+ Self::custom(Config::figment())
+ }
+
+ pub fn custom<T: Provider>(provider: T) -> Result<Self> {
+ Config::from(Figment::from(provider))
+ .map_err(Error::from)
+ .map(|config| Self { config })
+ }
+
+ pub fn clone_from_latest(&self, name: PathBuf, parent: PathBuf) -> Result<FileSystem> {
+ Self::get_file_system(parent)?
+ .get_latest_snapshot()?
+ .ok_or_else(|| Error::Snapshot("No snapshot found".into()))?
+ .clone_into_file_system(name)?
+ .set_quota(self.config.quota)
+ }
+
+ pub(super) fn get_file_systems() -> Result<Vec<FileSystem>> {
+ Command::new("zfs")
+ .arg("list")
+ .arg("-H")
+ .arg("-o")
+ .arg("name")
+ .output()
+ .map(|o| String::from_utf8(o.stdout))?
+ .map_err(|err| Error::FileSystem(format!("Failed to parse command output: {:?}", err)))?
+ .split_whitespace()
+ .map(FileSystem::try_from)
+ .collect()
+ }
+
+ fn get_file_system(name: PathBuf) -> Result<FileSystem> {
+ Self::get_file_systems()?
+ .into_iter()
+ .find(|fs| PathBuf::from(&fs.value).ends_with(&name))
+ .ok_or_else(|| Error::FileSystem("No file system found".into()))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn zfs_list() {
+ use super::*;
+ assert!(ZFS::get_file_systems().is_ok());
+ }
+}
diff --git a/zoned/src/api.rs b/zoned/src/api.rs
index fa98562..a1a892e 100644
--- a/zoned/src/api.rs
+++ b/zoned/src/api.rs
@@ -6,16 +6,17 @@ use rocket_okapi::{
swagger_ui::{make_swagger_ui, SwaggerUIConfig},
};
use zone_core::{Container, PartialEqOrDefault};
+use zone_zfs::ZFS;
-use crate::{Error, Result};
+use crate::{Config, Error, Result};
/// # Test endpoint
///
/// Returns a list of containers based on the query.
#[openapi(tag = "Testing")]
#[get("/test")]
-pub fn test_endpoint(zfs_config: &State<zone_zfs::Config>) -> Json<String> {
- Json(zfs_config.quota.to_owned())
+pub fn test_endpoint(zfs: &State<zone_zfs::ZFS>) -> Json<String> {
+ Json(zfs.config.pool_name.to_owned())
}
/// List containers
@@ -25,10 +26,16 @@ pub fn test_endpoint(zfs_config: &State<zone_zfs::Config>) -> Json<String> {
#[get("/container/list?<container..>")]
pub fn container_list(container: Container) -> Json<Vec<Container>> {
zone_nspawn::get_containers()
+ .unwrap_or_else(|_err| {
+ todo!("Log this error");
+ Default::default()
+ })
.into_iter()
.map(|c| {
- c.try_into()
- .unwrap_or_else(|_err| todo!("Log this error and return `Container::default()`"))
+ c.try_into().unwrap_or_else(|_err| {
+ todo!("Log this error");
+ Default::default()
+ })
})
.filter(|c| container.eq_or_default(c))
.collect::<Vec<Container>>()
@@ -42,20 +49,23 @@ pub fn container_list(container: Container) -> Json<Vec<Container>> {
#[post("/container", data = "<container>")]
fn create_container(
container: Json<Container>,
- zfs_config: &State<zone_zfs::Config>,
+ zfs: &State<zone_zfs::ZFS>,
) -> Result<Json<Container>> {
- zone_zfs::create_file_system(
- container.template.clone(),
- format!("{}-{}", container.user, container.id),
- zfs_config,
+ zfs.clone_from_latest(
+ format!("{}-{}", container.user, container.id).into(),
+ container.template.to_owned().into(),
)?
.try_into()
.map_err(Error::from)
.map(Container::into)
}
-pub fn build_rocket(config: crate::Config) -> Rocket<Build> {
- rocket::custom(config.rocket_config)
+pub fn build_zfs(config: &Config) -> Result<ZFS> {
+ zone_zfs::ZFS::custom(&config.zfs_config).map_err(Error::from)
+}
+
+pub fn build_rocket(config: &Config) -> Rocket<Build> {
+ rocket::custom(config.rocket_config.to_owned())
.mount(
"/",
openapi_get_routes![test_endpoint, container_list, create_container,],
@@ -82,5 +92,4 @@ pub fn build_rocket(config: crate::Config) -> Rocket<Build> {
..Default::default()
}),
)
- .manage(config.zfs_config)
}
diff --git a/zoned/src/config.rs b/zoned/src/config.rs
new file mode 100644
index 0000000..aa16360
--- /dev/null
+++ b/zoned/src/config.rs
@@ -0,0 +1,8 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Default, Serialize, Deserialize)]
+pub struct Config {
+ pub(crate) rocket_config: rocket::Config,
+
+ pub(crate) zfs_config: zone_zfs::Config,
+}
diff --git a/zoned/src/error.rs b/zoned/src/error.rs
new file mode 100644
index 0000000..14b30db
--- /dev/null
+++ b/zoned/src/error.rs
@@ -0,0 +1,52 @@
+use rocket::{
+ http::Status,
+ response::{self, Responder},
+ Request,
+};
+use rocket_okapi::{
+ gen::OpenApiGenerator, okapi::openapi3::Responses, response::OpenApiResponderInner,
+ util::ensure_status_code_exists,
+};
+use thiserror::Error;
+use zone_core::Container;
+
+pub type Result<T> = std::result::Result<T, Error>;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ #[error("Container Error {0:?}")]
+ Container(Container),
+
+ #[error("ZFS Error {source:?}")]
+ ZFS {
+ #[from]
+ source: zone_zfs::Error,
+ },
+
+ #[error("NSpawn Error {source:?}")]
+ Nspawn {
+ #[from]
+ source: zone_nspawn::Error,
+ },
+
+ #[error(transparent)]
+ Other(#[from] anyhow::Error),
+}
+
+impl<'r, 'o: 'r> Responder<'r, 'o> for Error {
+ fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
+ // https://stuarth.github.io/rocket-error-handling/
+ // match self {
+ // _ => Status::InternalServerError.respond_to(req),
+ // }
+ Status::InternalServerError.respond_to(req)
+ }
+}
+
+impl OpenApiResponderInner for Error {
+ fn responses(_gen: &mut OpenApiGenerator) -> rocket_okapi::Result<Responses> {
+ let mut responses = Responses::default();
+ ensure_status_code_exists(&mut responses, 500);
+ Ok(responses)
+ }
+}
diff --git a/zoned/src/lib.rs b/zoned/src/lib.rs
index 4784ff5..6e300dc 100644
--- a/zoned/src/lib.rs
+++ b/zoned/src/lib.rs
@@ -1,62 +1,8 @@
-use rocket::{
- http::Status,
- response::{self, Responder},
- Request,
-};
-use rocket_okapi::{
- gen::OpenApiGenerator, okapi::openapi3::Responses, response::OpenApiResponderInner,
- util::ensure_status_code_exists,
-};
-use serde::{Deserialize, Serialize};
-use thiserror::Error;
-use zone_core::Container;
+pub use config::Config;
+pub use error::{Error, Result};
-type Result<T> = std::result::Result<T, Error>;
+pub mod error;
-#[derive(Error, Debug)]
-pub enum Error {
- #[error("Container Error {0:?}")]
- Container(Container),
-
- #[error("ZFS Error {source:?}")]
- ZFS {
- #[from]
- source: zone_zfs::Error,
- },
-
- #[error("NSpawn Error {source:?}")]
- Nspawn {
- #[from]
- source: zone_nspawn::Error,
- },
-
- #[error(transparent)]
- Other(#[from] anyhow::Error),
-}
-
-impl<'r, 'o: 'r> Responder<'r, 'o> for Error {
- fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
- // https://stuarth.github.io/rocket-error-handling/
- // match self {
- // _ => Status::InternalServerError.respond_to(req),
- // }
- Status::InternalServerError.respond_to(req)
- }
-}
-
-impl OpenApiResponderInner for Error {
- fn responses(_gen: &mut OpenApiGenerator) -> rocket_okapi::Result<Responses> {
- let mut responses = Responses::default();
- ensure_status_code_exists(&mut responses, 500);
- Ok(responses)
- }
-}
-
-#[derive(Default, Serialize, Deserialize)]
-pub struct Config {
- pub(crate) rocket_config: rocket::Config,
-
- pub(crate) zfs_config: zone_zfs::Config,
-}
+pub mod config;
pub mod api;
diff --git a/zoned/src/main.rs b/zoned/src/main.rs
index 5ca2862..f9512a2 100644
--- a/zoned/src/main.rs
+++ b/zoned/src/main.rs
@@ -2,6 +2,7 @@ use figment::{
providers::{Env, Format, Serialized, Toml},
Figment,
};
+use std::process;
use zoned::{api, Config};
#[rocket::main]
@@ -12,7 +13,15 @@ async fn main() {
.extract()
.expect("Failed to parse config");
- match api::build_rocket(config).launch().await {
+ let zfs = match api::build_zfs(&config) {
+ Ok(zfs) => zfs,
+ Err(err) => {
+ eprintln!("ZFS error: {}", err);
+ process::exit(1)
+ }
+ };
+
+ match api::build_rocket(&config).manage(zfs).launch().await {
Ok(()) => println!("Rocket shut down gracefully."),
Err(err) => eprintln!("Rocket had an error: {}", err),
};