Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing errors related to "from_systemctl" #13

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
131 changes: 97 additions & 34 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ fn spawn_child(args: Vec<&str>) -> std::io::Result<Child> {
/// Invokes `systemctl $args` silently
fn systemctl(args: Vec<&str>) -> std::io::Result<ExitStatus> {
spawn_child(args)?.wait()

}

/// Invokes `systemctl $args` and captures stdout stream
Expand Down Expand Up @@ -65,18 +66,20 @@ fn systemctl_capture(args: Vec<&str>) -> std::io::Result<String> {
"Invalid utf8 data in stdout",
));
}

}

// if this is reached all if's above did not work
Err(Error::new(
ErrorKind::UnexpectedEof,
"systemctl stdout empty",
))

}

/// Forces given `unit` to (re)start
pub fn restart(unit: &str) -> std::io::Result<ExitStatus> {
systemctl(vec!["restart", unit])
pub fn _restart(unit: &str) -> std::io::Result<ExitStatus> {
_systemctl(vec!["restart", unit])
}

/// Forces given `unit` to start
Expand All @@ -85,8 +88,8 @@ pub fn start(unit: &str) -> std::io::Result<ExitStatus> {
}

/// Forces given `unit` to stop
pub fn stop(unit: &str) -> std::io::Result<ExitStatus> {
systemctl(vec!["stop", unit])
pub fn _stop(unit: &str) -> std::io::Result<ExitStatus> {
_systemctl(vec!["stop", unit])
}

/// Triggers reload for given `unit`
Expand Down Expand Up @@ -127,20 +130,20 @@ pub fn is_active(unit: &str) -> std::io::Result<bool> {

/// Isolates given unit, only self and its dependencies are
/// now actively running
pub fn isolate(unit: &str) -> std::io::Result<ExitStatus> {
systemctl(vec!["isolate", unit])
pub fn _isolate(unit: &str) -> std::io::Result<ExitStatus> {
_systemctl(vec!["isolate", unit])
}

/// Freezes (halts) given unit.
/// This operation might not be feasible.
pub fn freeze(unit: &str) -> std::io::Result<ExitStatus> {
systemctl(vec!["freeze", unit])
pub fn _freeze(unit: &str) -> std::io::Result<ExitStatus> {
_systemctl(vec!["freeze", unit])
}

/// Unfreezes given unit (recover from halted state).
/// This operation might not be feasible.
pub fn unfreeze(unit: &str) -> std::io::Result<ExitStatus> {
systemctl(vec!["thaw", unit])
pub fn _unfreeze(unit: &str) -> std::io::Result<ExitStatus> {
_systemctl(vec!["thaw", unit])
}

/// Returns `true` if given `unit` exists,
Expand Down Expand Up @@ -174,6 +177,7 @@ pub fn list_units_full(
}
let mut result: Vec<UnitList> = Vec::new();
let content = systemctl_capture(args)?;

let lines = content
.lines()
.filter(|line| line.contains('.') && !line.ends_with('.'));
Expand All @@ -191,6 +195,7 @@ pub fn list_units_full(
state: parsed[1].to_string(),
vendor_preset,
})

}
Ok(result)
}
Expand Down Expand Up @@ -222,13 +227,15 @@ pub fn list_units(
}

/// Returns list of services that are currently declared as disabled

pub fn list_disabled_services() -> std::io::Result<Vec<String>> {
list_units(Some("service"), Some("disabled"), None)
}

/// Returns list of services that are currently declared as enabled
pub fn list_enabled_services() -> std::io::Result<Vec<String>> {
list_units(Some("service"), Some("enabled"), None)

}

/// `AutoStartStatus` describes the Unit current state
Expand All @@ -250,6 +257,31 @@ pub enum AutoStartStatus {
Indirect,
#[strum(serialize = "transient")]
Transient,

#[strum(serialize = "enabled-runtime")]
EnabledRuntime,

}

impl ToString for AutoStartStatus{
fn to_string(&self) -> String {
match self {
AutoStartStatus::Static => "static".to_string(),
AutoStartStatus::Enabled => "enabled".to_string(),
AutoStartStatus::Disabled => "disabled".to_string(),
AutoStartStatus::Generated => "generated".to_string(),
AutoStartStatus::Indirect => "indirect".to_string(),
AutoStartStatus::Transient => "transient".to_string(),
AutoStartStatus::EnabledRuntime => "enabled-runtime".to_string(),
}
}
}

impl Default for AutoStartStatus {
fn default() -> AutoStartStatus {
AutoStartStatus::Disabled
}

}

/// `Type` describes a Unit declaration Type in systemd
Expand All @@ -275,6 +307,34 @@ pub enum Type {
Path,
#[strum(serialize = "target")]
Target,
#[strum(serialize = "swap")]
Swap,
#[strum(serialize = "aa-prompt-listener")]
AaPromptListener,
#[strum(serialize = "system-shutdown")]
SystemShutdown,
#[strum(serialize = "recovery-chooser-trigger")]
RecoveryChooserTrigger,
#[strum(serialize = "failure")]
Failure,
#[strum(serialize = "unmount")]
Unmount,
#[strum(serialize = "autoimport")]
AutoImport,
#[strum(serialize = "snap-repair")]
SnapRepair,
#[strum(serialize = "mounts-pre")]
MountsPre,
#[strum(serialize = "mounts-post")]
MountsPost,
#[strum(serialize = "mounts")]
Mounts,
#[strum(serialize = "seeded")]
Seeded,
#[strum(serialize = "apparmor")]
Apparmor,
#[strum(serialize = "core-fixup")]
CoreFixup,
}

/// `State` describes a Unit current state
Expand All @@ -288,7 +348,9 @@ pub enum State {
Loaded,
}

/*



/// Process
#[derive(Clone, Debug)]
pub struct Process {
Expand All @@ -302,16 +364,7 @@ pub struct Process {
status: String,
}

impl Default for Process {
fn default() -> Process {
Process {
pid: 0,
command: Default::default(),
code: Default::default(),
status: Default::default(),
}
}
}*/


/// Doc describes types of documentation possibly
/// available for a systemd `unit`
Expand All @@ -326,14 +379,14 @@ pub enum Doc {

impl Doc {
/// Unwrapps self as `Man` page
pub fn as_man(&self) -> Option<&str> {
pub fn _as_man(&self) -> Option<&str> {
match self {
Doc::Man(s) => Some(s),
_ => None,
}
}
/// Unwrapps self as webpage `Url`
pub fn as_url(&self) -> Option<&str> {
pub fn _as_url(&self) -> Option<&str> {
match self {
Doc::Url(s) => Some(s),
_ => None,
Expand Down Expand Up @@ -457,6 +510,7 @@ impl Unit {
u.description = Some(itertools::join(&items, " "));
}
}

let (name, utype_raw) = name_raw
.rsplit_once('.')
.expect("Unit is missing a Type, this should not happen!");
Expand All @@ -480,6 +534,7 @@ impl Unit {
Ok(x) => x,
Err(_) => AutoStartStatus::Disabled,
};

if items.len() > 2 {
// preset is optionnal ?
u.preset = items[2].trim().ends_with("enabled");
Expand Down Expand Up @@ -574,8 +629,8 @@ impl Unit {
}

/// Restarts Self by invoking `systemctl`
pub fn restart(&self) -> std::io::Result<ExitStatus> {
restart(&self.name)
pub fn _restart(&self) -> std::io::Result<ExitStatus> {
_restart(&self.name)
}

/// Starts Self by invoking `systemctl`
Expand Down Expand Up @@ -614,28 +669,28 @@ impl Unit {
}

/// Returns `true` if Self is actively running
pub fn is_active(&self) -> std::io::Result<bool> {
pub fn _is_active(&self) -> std::io::Result<bool> {
is_active(&self.name)
}

/// `Isolate` Self, meaning stops all other units but
/// self and its dependencies
pub fn isolate(&self) -> std::io::Result<ExitStatus> {
isolate(&self.name)
pub fn _isolate(&self) -> std::io::Result<ExitStatus> {
_isolate(&self.name)
}

/// `Freezes` Self, halts self and CPU load will
/// no longer be dedicated to its execution.
/// This operation might not be feasible.
/// `unfreeze()` is the mirror operation
pub fn freeze(&self) -> std::io::Result<ExitStatus> {
freeze(&self.name)
pub fn _freeze(&self) -> std::io::Result<ExitStatus> {
_freeze(&self.name)
}

/// `Unfreezes` Self, exists halted state.
/// This operation might not be feasible.
pub fn unfreeze(&self) -> std::io::Result<ExitStatus> {
unfreeze(&self.name)
pub fn _unfreeze(&self) -> std::io::Result<ExitStatus> {
_unfreeze(&self.name)
}

/// Returns `true` if given `unit` exists,
Expand All @@ -646,6 +701,8 @@ impl Unit {
}
}



#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -694,12 +751,12 @@ mod test {
}
#[test]
fn test_disabled_services() {
let services = list_disabled_services().unwrap();
let services = _list_disabled_services().unwrap();
println!("disabled services: {:#?}", services)
}
#[test]
fn test_enabled_services() {
let services = list_enabled_services().unwrap();
let services = _list_enabled_services().unwrap();
println!("enabled services: {:#?}", services)
}
#[test]
Expand All @@ -726,23 +783,29 @@ mod test {
let result = u.map_err(|e| e.kind());
let expected = Err(ErrorKind::NotFound);
assert_eq!(expected, result);

}

#[test]
fn test_service_unit_construction() {

let units = list_units(None, None, None).unwrap(); // all units

for unit in units {
let unit = unit.as_str();
if unit.contains('@') {
// not testing this one
// would require @x service # identification / enumeration
continue;
}

let c0 = unit.chars().next().unwrap();
if c0.is_alphanumeric() {
// valid unit name --> run test
let u = Unit::from_systemctl(unit).unwrap();

println!("####################################");

println!("Unit: {:#?}", u);
println!("active: {}", u.active);
println!("preset: {}", u.preset);
Expand Down
Loading