use clap::Parser; mod errors; use errors::CliError; use tabular::{row, Table}; use reqwest::{blocking::Client, StatusCode}; use solarlib::planet::Planet; /// Manage solard and homeworld instances #[derive(Parser)] #[clap(author, version, about)] struct Args { /// The solard server to connect to server: String, /// The action to be taken #[clap(subcommand)] action: Action } #[derive(clap::Subcommand)] enum Action { /// List planets on the server List, /// Shuts down a virtual machine Stop { /// The UUID of the machine to stop uuid: String, #[clap(long, short)] force: bool }, Start { /// The UUID of the machine to start uuid: String, }, Pause { /// The UUID of the machine to pause uuid: String, }, Reboot { uuid: String, #[clap(long, short)] force: bool } } fn main() { color_eyre::install().unwrap(); let args = Args::parse(); let client = reqwest::blocking::Client::new(); let root = args.server.clone(); match args.action { Action::List => { list(args, client).unwrap(); }, Action::Stop { uuid, force } => { stop(root, client, uuid, force).unwrap(); }, Action::Start { uuid } => { start(root, client, uuid).unwrap(); }, Action::Pause { uuid } => { pause(root, client, uuid).unwrap(); }, Action::Reboot { uuid, force } => { reboot(root, client, uuid, force).unwrap(); } }; } fn list(a: Args, c: Client) -> Result<(), CliError> { let res: Vec = c.get(format!("http://{}/planets/list", a.server)).send()?.json()?; let mut table = Table::new("{:<} {:<} {:<}"); table.add_row(row!( "name", "uuid", "status") ); for p in res { table.add_row(row!( &p.name, &p.uuid, if p.orbiting { "Running" } else { "Not running" }, )); } println!("{}", table); Ok(()) } fn stop(server: String, c: Client, u: String, f: bool) -> Result<(), CliError> { let mut url = format!("http://{}/planets/{}/shutdown", server, u); if f { url.push_str("/hard"); } let res = c.post(url).send()?; match res.status() { StatusCode::OK => { println!("Stopped."); }, _ => { return Err(CliError::Cli(format!("Could not stop VM: {}", res.text()?))); }, }; Ok(()) } fn start(server: String, c: Client, u: String) -> Result<(), CliError> { let res = c.post(format!("http://{}/planets/{}/start", server, u)).send()?; match res.status() { StatusCode::OK => { println!("Started."); }, _ => { return Err(CliError::Cli(format!("Could not start VM: {}", res.text()?))); }, }; Ok(()) } fn pause(server: String, c: Client, u: String) -> Result<(), CliError> { let res = c.post(format!("http://{}/planets/{}/pause", server, u)).send()?; match res.status() { StatusCode::OK => { println!("Paused."); }, _ => { return Err(CliError::Cli(format!("Could not pause VM: {}", res.text()?))); }, }; Ok(()) } fn reboot(server: String, c: Client, u: String, f: bool) -> Result<(), CliError> { let mut url = format!("http://{}/planets/{}/reboot", server, u); if f { url.push_str("/hard"); } let res = c.post(url).send()?; match res.status() { StatusCode::OK => { println!("Rebooted."); }, _ => { return Err(CliError::Cli(format!("Could not reboot VM: {}", res.text()?))); }, }; Ok(()) }