use super::{command_mechanism, ActionSpec};
use sysknife_types::RiskLevel;
pub fn specs() -> Vec<ActionSpec> {
vec![
distrobox_list(),
distrobox_create("dev", "ubuntu:24.04"),
distrobox_remove("dev"),
]
}
pub fn distrobox_list() -> ActionSpec {
ActionSpec {
action_name: "DistroboxList",
mechanism: command_mechanism("distrobox", ["list"]),
risk_level: RiskLevel::Low,
reboot_required: false,
rollback_available: false,
}
}
pub fn distrobox_create(name: &str, image: &str) -> ActionSpec {
ActionSpec {
action_name: "DistroboxCreate",
mechanism: command_mechanism(
"distrobox",
["create", "--yes", "--name", name, "--image", image],
),
risk_level: RiskLevel::Medium,
reboot_required: false,
rollback_available: false,
}
}
pub fn distrobox_remove(name: &str) -> ActionSpec {
ActionSpec {
action_name: "DistroboxRemove",
mechanism: command_mechanism("distrobox", ["rm", "--force", name]),
risk_level: RiskLevel::Medium,
reboot_required: false,
rollback_available: false,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::actions::ActionMechanism;
fn extract_args(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 distrobox_list_action_name() {
assert_eq!(distrobox_list().action_name, "DistroboxList");
}
#[test]
fn distrobox_list_argv() {
let spec = distrobox_list();
let (prog, args) = extract_args(&spec);
assert_eq!(prog, "distrobox");
assert!(args.contains(&"list"));
}
#[test]
fn distrobox_list_risk_low() {
assert_eq!(distrobox_list().risk_level, RiskLevel::Low);
}
#[test]
fn distrobox_list_no_reboot() {
assert!(!distrobox_list().reboot_required);
}
#[test]
fn distrobox_create_action_name() {
assert_eq!(
distrobox_create("dev", "ubuntu:24.04").action_name,
"DistroboxCreate"
);
}
#[test]
fn distrobox_create_argv_includes_name_and_image() {
let spec = distrobox_create("mybox", "fedora:41");
let (prog, args) = extract_args(&spec);
assert_eq!(prog, "distrobox");
assert!(args.contains(&"create"));
assert!(args.contains(&"--name"));
assert!(args.contains(&"mybox"));
assert!(args.contains(&"--image"));
assert!(args.contains(&"fedora:41"));
}
#[test]
fn distrobox_create_includes_yes_flag() {
let spec = distrobox_create("mybox", "ubuntu:24.04");
let (_, args) = extract_args(&spec);
assert!(
args.contains(&"--yes"),
"DistroboxCreate must pass --yes so it never prompts on a TTY-less daemon"
);
}
#[test]
fn distrobox_create_risk_medium() {
assert_eq!(
distrobox_create("x", "ubuntu:22.04").risk_level,
RiskLevel::Medium
);
}
#[test]
fn distrobox_remove_action_name() {
assert_eq!(distrobox_remove("dev").action_name, "DistroboxRemove");
}
#[test]
fn distrobox_remove_uses_force_flag() {
let spec = distrobox_remove("dev");
let (prog, args) = extract_args(&spec);
assert_eq!(prog, "distrobox");
assert!(args.contains(&"rm"));
assert!(args.contains(&"--force"));
assert!(args.contains(&"dev"));
}
#[test]
fn distrobox_remove_risk_medium() {
assert_eq!(distrobox_remove("dev").risk_level, RiskLevel::Medium);
}
#[test]
fn specs_covers_all_action_names() {
let expected = ["DistroboxList", "DistroboxCreate", "DistroboxRemove"];
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}");
}
}
}