summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2022-07-09 18:54:49 -0400
committerCara Salter <cara@devcara.com>2022-07-09 18:54:49 -0400
commitf7aedd98bff7b208da8dd70917fcf57fc140f0b7 (patch)
tree235a8bfcd321cf203fee2f2a9c5449b6030d9fc1
parentd6ed1d4ad337a9e120e583fe91882b73e2e2d700 (diff)
downloadsolarctl-master.tar.gz
solarctl-master.zip
-rw-r--r--flake.lock74
-rw-r--r--flake.nix40
-rw-r--r--src/main.rs181
3 files changed, 106 insertions, 189 deletions
diff --git a/flake.lock b/flake.lock
deleted file mode 100644
index 082400c..0000000
--- a/flake.lock
+++ /dev/null
@@ -1,74 +0,0 @@
-{
- "nodes": {
- "flake-utils": {
- "locked": {
- "lastModified": 1653893745,
- "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
- "owner": "numtide",
- "repo": "flake-utils",
- "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
- "type": "github"
- },
- "original": {
- "owner": "numtide",
- "repo": "flake-utils",
- "type": "github"
- }
- },
- "naersk": {
- "inputs": {
- "nixpkgs": "nixpkgs"
- },
- "locked": {
- "lastModified": 1654608517,
- "narHash": "sha256-KIxHjDDJYhoiLanLjpeAk5AuZsfip8M62JhkuloEGb0=",
- "owner": "nix-community",
- "repo": "naersk",
- "rev": "14997a79cd78fe34ad6390f18a327ee0593e5eec",
- "type": "github"
- },
- "original": {
- "owner": "nix-community",
- "repo": "naersk",
- "type": "github"
- }
- },
- "nixpkgs": {
- "locked": {
- "lastModified": 1654665288,
- "narHash": "sha256-7blJpfoZEu7GKb84uh3io/5eSJNdaagXD9d15P9iQMs=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "43ecbe7840d155fa933ee8a500fb00dbbc651fc8",
- "type": "github"
- },
- "original": {
- "id": "nixpkgs",
- "type": "indirect"
- }
- },
- "nixpkgs_2": {
- "locked": {
- "lastModified": 1654665288,
- "narHash": "sha256-7blJpfoZEu7GKb84uh3io/5eSJNdaagXD9d15P9iQMs=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "43ecbe7840d155fa933ee8a500fb00dbbc651fc8",
- "type": "github"
- },
- "original": {
- "id": "nixpkgs",
- "type": "indirect"
- }
- },
- "root": {
- "inputs": {
- "flake-utils": "flake-utils",
- "naersk": "naersk",
- "nixpkgs": "nixpkgs_2"
- }
- }
- },
- "root": "root",
- "version": 7
-}
diff --git a/flake.nix b/flake.nix
deleted file mode 100644
index 3dff665..0000000
--- a/flake.nix
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- inputs = {
- flake-utils.url = "github:numtide/flake-utils";
- naersk.url = "github:nix-community/naersk";
- };
-
- outputs = { self, nixpkgs, flake-utils, naersk }:
- flake-utils.lib.eachDefaultSystem (
- system: let
- pkgs = nixpkgs.legacyPackages."${system}";
- naersk-lib = naersk.lib."${system}";
-
- deps = with pkgs; [
- openssl
- pkg-config
- libvirt
- ];
- in
- rec {
- # `nix build`
- packages.solarctl = naersk-lib.buildPackage {
- pname = "solarctl";
- root = ./.;
- nativeBuildInputs = deps;
- };
- defaultPackage = packages.solarctl;
-
- # `nix run`
- apps.solarctl = flake-utils.lib.mkApp {
- drv = packages.solarctl;
- };
- defaultApp = apps.solarctl;
-
- # `nix develop`
- devShell = pkgs.mkShell {
- nativeBuildInputs = with pkgs; [ rustc cargo ] ++ deps;
- };
- }
- );
-}
diff --git a/src/main.rs b/src/main.rs
index 70fd438..1969398 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,11 +5,11 @@ use clap::Parser;
mod errors;
use errors::CliError;
use reqwest::header;
-use tabular::{row, Table};
use reqwest::{blocking::Client, StatusCode};
-use solarlib::planet::{Planet, Memory, CpuCount};
+use serde::{Deserialize, Serialize};
+use solarlib::planet::{CpuCount, Memory, Planet};
use solarlib::star::NewPlanet;
-use serde::{Serialize, Deserialize};
+use tabular::{row, Table};
/// Manage solard and homeworld instances
#[derive(Parser)]
@@ -19,12 +19,12 @@ struct Args {
server: String,
/// The action to be taken
#[clap(subcommand)]
- action: Action
+ action: Action,
}
#[derive(Serialize, Deserialize)]
struct ServerConfig {
- pub token: String
+ pub token: String,
}
#[derive(clap::Subcommand)]
@@ -37,7 +37,7 @@ enum Action {
uuid: String,
#[clap(long, short)]
- force: bool
+ force: bool,
},
Start {
/// The UUID of the machine to start
@@ -51,13 +51,13 @@ enum Action {
uuid: String,
#[clap(long, short)]
- force: bool
+ force: bool,
},
View {
- uuid: String
+ uuid: String,
},
- Create {
+ Create {
max_mem: u64,
max_cpus: u64,
@@ -67,14 +67,14 @@ enum Action {
name: String,
/// The Sha256 hash of the ship
- ship: String
+ ship: String,
},
/// Goes through the first-time authentication process to create a token that expires after one
/// year, storing it in the process.
Login {
- key: String
- }
+ key: String,
+ },
}
fn main() {
@@ -82,70 +82,79 @@ fn main() {
let args = Args::parse();
let xdg_dirs = xdg::BaseDirectories::with_profile("solarctl", args.server.clone()).unwrap();
- let mut headers = header::HeaderMap::new();
+ let mut headers = header::HeaderMap::new();
if let Some(p) = xdg_dirs.find_config_file("config.json") {
- let c = fs::read_to_string(p).unwrap();
+ let c = fs::read_to_string(p).unwrap();
if let Ok(cfg) = serde_json::from_str::<ServerConfig>(&c) {
- headers.insert(header::AUTHORIZATION, header::HeaderValue::from_str(&cfg.token).unwrap());
+ headers.insert(
+ header::AUTHORIZATION,
+ header::HeaderValue::from_str(&cfg.token).unwrap(),
+ );
}
-
} else {
- println!("No config file found! You will need to authenticate with the `login` subcommand");
+ println!("No config file found! You will need to authenticate with the `login` subcommand");
}
- let client = reqwest::blocking::ClientBuilder::new().default_headers(headers).build().unwrap();
+ let client = reqwest::blocking::ClientBuilder::new()
+ .default_headers(headers)
+ .build()
+ .unwrap();
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();
}
Action::View { uuid } => {
view(root, uuid).unwrap();
- },
- Action::Create { max_mem, max_cpus, disk_size_mb, name, ship } => {
+ }
+ Action::Create {
+ max_mem,
+ max_cpus,
+ disk_size_mb,
+ name,
+ ship,
+ } => {
create(root, client, max_mem, max_cpus, disk_size_mb, name, ship).unwrap();
- },
+ }
Action::Login { key } => {
login(root, client, key);
}
};
}
-
fn list(a: Args, c: Client) -> Result<(), CliError> {
- let res: Vec<Planet> = c.get(format!("http://{}/planets/list", a.server)).send()?.json()?;
+ let res: Vec<Planet> = c
+ .get(format!("http://{}/planets/list", a.server))
+ .send()?
+ .json()?;
let mut table = Table::new("{:<} | {:<} | {:<} | {:<}");
- table.add_row(row!(
- "name", "uuid", "status", "running")
- );
- table.add_row(row!(
- "----", "----", "------", "-------")
- );
+ table.add_row(row!("name", "uuid", "status", "running"));
+ table.add_row(row!("----", "----", "------", "-------"));
for p in res {
table.add_row(row!(
- &p.name,
- &p.uuid,
- &p.status,
- if p.orbiting { "yes" } else { "no" },
- ));
+ &p.name,
+ &p.uuid,
+ &p.status,
+ if p.orbiting { "yes" } else { "no" },
+ ));
}
println!("{}", table);
@@ -163,40 +172,50 @@ fn stop(server: String, c: Client, u: String, f: bool) -> Result<(), CliError> {
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()?;
+ 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()?)));
- },
+ 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()?;
+ 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()?)));
- },
+ return Err(CliError::Cli(format!(
+ "Could not pause VM: {}",
+ res.text()?
+ )));
+ }
};
Ok(())
@@ -212,10 +231,13 @@ fn reboot(server: String, c: Client, u: String, f: bool) -> Result<(), CliError>
match res.status() {
StatusCode::OK => {
println!("Rebooted.");
- },
+ }
_ => {
- return Err(CliError::Cli(format!("Could not reboot VM: {}", res.text()?)));
- },
+ return Err(CliError::Cli(format!(
+ "Could not reboot VM: {}",
+ res.text()?
+ )));
+ }
};
Ok(())
@@ -229,14 +251,23 @@ fn view(server: String, u: String) -> Result<(), CliError> {
.arg("-c")
.arg(qemu_url)
.arg(u)
- .output() {
- println!("Could not run virt-viewer: {}", e);
- }
+ .output()
+ {
+ println!("Could not run virt-viewer: {}", e);
+ }
Ok(())
}
-fn create(s: String, c: Client, mem: u64, cpus: u64, disk_size: u64, name: String, ship: String) -> Result<(), CliError> {
+fn create(
+ s: String,
+ c: Client,
+ mem: u64,
+ cpus: u64,
+ disk_size: u64,
+ name: String,
+ ship: String,
+) -> Result<(), CliError> {
let url = format!("http://{}/planets/new", s);
let new_p: NewPlanet = NewPlanet {
@@ -244,7 +275,7 @@ fn create(s: String, c: Client, mem: u64, cpus: u64, disk_size: u64, name: Strin
ship,
disk_size_mb: disk_size,
max_mem: Memory(mem),
- max_cpus: CpuCount(cpus)
+ max_cpus: CpuCount(cpus),
};
println!("Creating new planet...");
@@ -256,9 +287,12 @@ fn create(s: String, c: Client, mem: u64, cpus: u64, disk_size: u64, name: Strin
let js: Planet = res.json()?;
println!("Created. UUID: {}", js.uuid);
- },
+ }
_ => {
- return Err(CliError::Cli(format!("Could not create VM: {}", res.text()?)));
+ return Err(CliError::Cli(format!(
+ "Could not create VM: {}",
+ res.text()?
+ )));
}
};
@@ -274,27 +308,24 @@ fn login(s: String, c: Client, k: String) -> Result<(), CliError> {
match res.status() {
StatusCode::OK => {
let token = res.text()?;
- let xdg_dirs = xdg::BaseDirectories::with_profile("solarctl", s).unwrap();
-
- if let Some(p) = xdg_dirs.find_config_file("config.json") {
- let cfg = ServerConfig {
- token
- };
+ let xdg_dirs = xdg::BaseDirectories::with_profile("solarctl", s).unwrap();
- fs::write(p, serde_json::to_string_pretty(&cfg).unwrap()).unwrap();
+ if let Some(p) = xdg_dirs.find_config_file("config.json") {
+ let cfg = ServerConfig { token };
- } else {
- let p = xdg_dirs.place_config_file("config.json").unwrap();
- let cfg = ServerConfig {
- token
- };
+ fs::write(p, serde_json::to_string_pretty(&cfg).unwrap()).unwrap();
+ } else {
+ let p = xdg_dirs.place_config_file("config.json").unwrap();
+ let cfg = ServerConfig { token };
- fs::write(p, serde_json::to_string_pretty(&cfg).unwrap()).unwrap();
- }
-
- },
+ fs::write(p, serde_json::to_string_pretty(&cfg).unwrap()).unwrap();
+ }
+ }
_ => {
- return Err(CliError::Cli(format!("Could not authenticate: {}", res.text()?)));
+ return Err(CliError::Cli(format!(
+ "Could not authenticate: {}",
+ res.text()?
+ )));
}
};