utmd 0.1.3

Minimalist developer sandbox and disposable VMs for UTM on macOS.
Documentation
use clap::{Args, Parser, Subcommand, ValueEnum};

#[derive(Parser, Debug)]
#[command(
    name = "utmd",
    about = "Disposable VM sandbox manager for UTM",
    long_about = "A developer tool to clone, boot, and clean disposable UTM sandbox environments."
)]
pub struct Cli {
    #[arg(long, global = true)]
    pub json: bool,
    #[arg(long, global = true)]
    pub quiet: bool,
    #[arg(long, global = true)]
    pub yes: bool,
    #[arg(long, global = true)]
    pub dry_run: bool,
    #[arg(long, global = true)]
    pub config: Option<String>,
    #[command(subcommand)]
    pub command: Commands,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
    #[command(
        about = "clone a new sandbox VM from a template",
        after_help = "examples:\n  utmd clone linux\n  utmd clone linux --name sandbox1\n  utmd clone macos --name-template \"{prefix}{os}-{date}-{rand}\""
    )]
    Clone(CloneArgs),
    #[command(
        about = "list managed or filtered VMs",
        after_help = "examples:\n  utmd list\n  utmd list --prefix \"\"\n  utmd list --prefix utmd- --os linux"
    )]
    List(ListArgs),
    #[command(
        about = "show details for a VM",
        after_help = "examples:\n  utmd status utmd-linux-abc123"
    )]
    Status(NameArgs),
    #[command(
        about = "start a VM",
        after_help = "examples:\n  utmd start utmd-linux-abc123\n  utmd --dry-run start utmd-linux-abc123"
    )]
    Start(NameArgs),
    #[command(
        about = "stop a VM",
        after_help = "examples:\n  utmd stop utmd-linux-abc123\n  utmd --dry-run stop utmd-linux-abc123"
    )]
    Stop(NameArgs),
    #[command(
        about = "open a VM in the UTM app",
        after_help = "examples:\n  utmd open utmd-linux-abc123"
    )]
    Open(NameArgs),
    #[command(
        about = "delete a single VM",
        after_help = "examples:\n  utmd delete utmd-linux-abc123\n  utmd --yes delete utmd-linux-abc123"
    )]
    Delete(DeleteArgs),
    #[command(
        about = "delete multiple VMs by filters",
        after_help = "examples:\n  utmd delete-all\n  utmd delete-all --prefix utmd- --os linux --older-than 24h --dry-run\n  utmd --yes delete-all --prefix utmd-"
    )]
    DeleteAll(DeleteAllArgs),
}

#[derive(Args, Debug)]
pub struct CloneArgs {
    #[arg(value_enum, value_name = "OS")]
    pub os_type: OsType,
    #[arg(long)]
    pub name: Option<String>,
    #[arg(long)]
    pub name_exact: bool,
    #[arg(long)]
    pub name_template: Option<String>,
    #[arg(long)]
    pub prefix: Option<String>,
    #[arg(long)]
    pub template: Option<String>,
}

#[derive(Args, Debug)]
pub struct ListArgs {
    #[arg(long)]
    pub prefix: Option<String>,
    #[arg(long, value_enum)]
    pub os: Option<OsType>,
}

#[derive(Args, Debug)]
pub struct NameArgs {
    pub name: String,
}

#[derive(Args, Debug)]
pub struct DeleteArgs {
    pub name: String,
    #[arg(long)]
    pub force: bool,
}

#[derive(Args, Debug)]
pub struct DeleteAllArgs {
    #[arg(long)]
    pub prefix: Option<String>,
    #[arg(long, value_enum)]
    pub os: Option<OsType>,
    #[arg(long)]
    pub older_than: Option<String>,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum OsType {
    Linux,
    Macos,
}

impl OsType {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Linux => "linux",
            Self::Macos => "macos",
        }
    }
}