wip: config find

This commit is contained in:
Suyono 2023-11-22 23:45:00 +11:00
parent 3cf595f08e
commit e1e0caf6c3
6 changed files with 104 additions and 3 deletions

View File

@ -6,6 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nix = {version = "0.27.1", features = ["process", "signal"]}
nix = {version = "0.27.1", features = ["process", "signal", "fs"]}
tokio = { version = "1.34.0", features = ["full"] }
tokio-util = "0.7.10"

View File

@ -4,5 +4,5 @@ use wingmate_rs::init;
#[tokio::main]
async fn main() -> Result<(), Box<dyn error::Error>> {
init::daemon::start().await
init::start().await
}

View File

@ -1 +1,10 @@
pub mod daemon;
mod daemon;
mod config;
pub(crate) mod error;
use std::error as std_err;
pub async fn start() -> Result<(), Box<dyn std_err::Error>> {
let _config = config::Config::find(vec![String::from("/etc/wingmate")])?;
daemon::start().await
}

65
src/init/config.rs Normal file
View File

@ -0,0 +1,65 @@
use std::fs;
use std::path::PathBuf;
use std::error as std_error;
use crate::init::error as wingmate_error;
use nix::unistd::{access, AccessFlags};
pub enum Command {
ShellPrefixed(String),
Direct(String)
}
pub struct Config {
pub services: Vec<Command>,
}
impl Config {
pub fn find(search_path: Vec<String>) -> Result<Config, Box<dyn std_error::Error>> {
if search_path.is_empty() {
return Err(wingmate_error::InvalidConfigSearchPathError.into());
}
let mut svc_commands: Vec<Command> = Vec::new();
for p in search_path {
let mut buf = PathBuf::new();
buf.push(p);
if let Ok(m) = fs::metadata(buf.as_path()) {
if m.is_dir() {
let svc = buf.join("services");
if let Ok(svc_iter) = fs::read_dir(svc.as_path()) {
for entry in svc_iter {
if let Ok(dirent) = entry {
let ep = dirent.path();
if let Ok(_) = access(ep.as_path(), AccessFlags::X_OK) {
// execute directly
svc_commands.push(Command::Direct(String::from(ep.as_path().to_string_lossy())));
} else {
// call with shell
svc_commands.push(Command::ShellPrefixed(String::from(ep.as_path().to_string_lossy())));
}
}
}
}
let cron = buf.join("cron");
if let Ok(cron_iter) = fs::read_dir(cron.as_path()) {
for entry in cron_iter {
if let Ok(_dirent) = entry {
// read the cron file
}
}
}
} else {
// reserve for future use; when we have a centralized config file
}
}
}
if svc_commands.is_empty() {
return Err(wingmate_error::NoServiceOrCronFoundError.into());
}
let config = Config { services: svc_commands };
Ok(config)
}
}

View File

@ -47,6 +47,8 @@ pub fn start_process(ts: &mut JoinSet<Result<(), Box<dyn error::Error + Send + S
}
}
}
} else {
break 'autorestart;
}
},
result = child.wait() => {

25
src/init/error.rs Normal file
View File

@ -0,0 +1,25 @@
use std::fmt;
use std::error;
#[derive(Debug, Clone)]
pub struct InvalidConfigSearchPathError;
impl fmt::Display for InvalidConfigSearchPathError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "invalid config search path")
}
}
impl error::Error for InvalidConfigSearchPathError {}
#[derive(Debug,Clone)]
pub struct NoServiceOrCronFoundError;
impl fmt::Display for NoServiceOrCronFoundError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "no service or cron found")
}
}
impl error::Error for NoServiceOrCronFoundError {}