pub mod launchd;
pub mod systemd;
pub mod task_scheduler;
use crate::error::OlError;
pub const ERR_SUPERVISION_UNSUPPORTED_OS: &str = "OL-1950";
pub const ERR_SUPERVISION_INSTALL_FAILED: &str = "OL-1951";
pub const ERR_SUPERVISION_BOOTSTRAP_FAILED: &str = "OL-1952";
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SupervisorKind {
Launchd,
Systemd,
TaskScheduler,
None,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SupervisionMode {
Active,
Deferred,
Disabled,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SupervisionConfig {
pub mode: SupervisionMode,
pub backend: SupervisorKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_reason: Option<String>,
}
impl Default for SupervisionConfig {
fn default() -> Self {
Self {
mode: SupervisionMode::Disabled,
backend: SupervisorKind::None,
disabled_reason: Some("not_initialized".into()),
}
}
}
pub trait Supervisor: Send + Sync {
fn kind(&self) -> SupervisorKind;
fn install(&self, binary_path: &std::path::Path) -> Result<(), OlError>;
fn uninstall(&self) -> Result<(), OlError>;
fn status(&self) -> Result<SupervisorStatus, OlError>;
}
#[derive(Debug, Clone)]
pub struct SupervisorStatus {
pub installed: bool,
pub running: bool,
pub description: String,
}
pub fn select_supervisor() -> Option<Box<dyn Supervisor>> {
select_supervisor_impl()
}
#[cfg(target_os = "macos")]
fn select_supervisor_impl() -> Option<Box<dyn Supervisor>> {
Some(Box::new(launchd::LaunchdSupervisor::new()))
}
#[cfg(target_os = "linux")]
fn select_supervisor_impl() -> Option<Box<dyn Supervisor>> {
if systemd::is_systemd_available() {
Some(Box::new(systemd::SystemdSupervisor::new()))
} else {
None
}
}
#[cfg(target_os = "windows")]
fn select_supervisor_impl() -> Option<Box<dyn Supervisor>> {
Some(Box::new(task_scheduler::TaskSchedulerSupervisor::new()))
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn select_supervisor_impl() -> Option<Box<dyn Supervisor>> {
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_supervision_config_is_disabled() {
let c = SupervisionConfig::default();
assert_eq!(c.mode, SupervisionMode::Disabled);
assert_eq!(c.backend, SupervisorKind::None);
}
#[test]
fn select_supervisor_returns_something_on_this_os() {
let sup = select_supervisor();
#[cfg(any(target_os = "macos", target_os = "windows"))]
assert!(sup.is_some());
let _ = sup;
}
}