use super::{command_mechanism, ActionSpec};
use sysknife_types::RiskLevel;
pub fn specs() -> Vec<ActionSpec> {
vec![livepatch_status()]
}
pub fn livepatch_status() -> ActionSpec {
ActionSpec {
action_name: "LivepatchStatus",
mechanism: command_mechanism("sudo", ["canonical-livepatch", "status", "--verbose"]),
risk_level: RiskLevel::Low,
reboot_required: false,
rollback_available: false,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::actions::ActionMechanism;
fn extract_cmd(spec: &ActionSpec) -> (&'static str, Vec<&str>) {
match &spec.mechanism {
ActionMechanism::Command { program, args } => {
(*program, args.iter().map(String::as_str).collect())
}
_ => panic!("expected Command mechanism"),
}
}
#[test]
fn livepatch_status_action_name() {
assert_eq!(livepatch_status().action_name, "LivepatchStatus");
}
#[test]
fn livepatch_status_risk_low() {
assert_eq!(livepatch_status().risk_level, RiskLevel::Low);
}
#[test]
fn livepatch_status_no_reboot() {
assert!(!livepatch_status().reboot_required);
}
#[test]
fn livepatch_status_no_rollback() {
assert!(!livepatch_status().rollback_available);
}
#[test]
fn livepatch_status_argv() {
let spec = livepatch_status();
let (prog, args) = extract_cmd(&spec);
assert_eq!(prog, "sudo");
assert!(args.contains(&"canonical-livepatch"));
assert!(args.contains(&"status"));
assert!(args.contains(&"--verbose"));
}
#[test]
fn specs_covers_all_action_names() {
let expected = ["LivepatchStatus"];
let spec_names: Vec<&str> = specs().iter().map(|s| s.action_name).collect();
for name in &expected {
assert!(spec_names.contains(name), "specs() missing {name}");
}
}
}