diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/errors.rs | 6 | ||||
-rw-r--r-- | src/handlers/planets.rs | 58 | ||||
-rw-r--r-- | src/main.rs | 15 |
3 files changed, 75 insertions, 4 deletions
diff --git a/src/errors.rs b/src/errors.rs index b22932f..e0a6df9 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -15,6 +15,12 @@ pub enum ServiceError { #[error("Not Found")] NotFound, + + #[error("Reqwest: {0}")] + Reqwest(#[from] reqwest::Error), + + #[error("Command error: {0}")] + Command(#[from] std::io::Error) } pub type StringResult<T = &'static str> = std::result::Result<T, ServiceError>; diff --git a/src/handlers/planets.rs b/src/handlers/planets.rs index 06773bc..2c66324 100644 --- a/src/handlers/planets.rs +++ b/src/handlers/planets.rs @@ -1,11 +1,17 @@ +use axum::Extension; +use axum_macros::debug_handler; use axum::{response::IntoResponse, Json, extract::Path}; +use solarlib::ship::{DbShip, Ship}; +use tokio::process::Command; use tracing::{error, instrument}; -use solarlib::star::Star; +use solarlib::star::{Star, NewPlanet}; use solarlib::planet::Planet; +use solarlib::errors::Error as SolarlibError; -use crate::{errors::*, get_star}; +use crate::{errors::*, get_star, State}; +use std::sync::Arc; pub async fn list() -> JsonResult<Json<Vec<Planet>>> { let con_url = std::env::var("QEMU_URL").unwrap_or("qemu:///system".to_string()); @@ -100,3 +106,51 @@ pub async fn force_shutdown(Path(uuid): Path<String>) -> NoneResult { Ok(()) } + +#[debug_handler] +pub async fn new_planet(Json(new_planet): Json<NewPlanet>) -> JsonResult<Json<Planet>> { + let hw_url = std::env::var("HOMEWORLD_URL").unwrap(); + + let ship_shasum = new_planet.clone().ship; + + let res: DbShip = reqwest::get(format!("http://{}/ships/get/{}", hw_url, ship_shasum)).await?.json().await?; + let ship: Ship = res.into(); + + let mut s = get_star()?; + + println!("{:?}", s); + + // Try to create right away, if the Ship already exists on the system, it'll go through. If + // not, we can download it by using the shasum + let r = s.planet(new_planet.clone().name, new_planet.max_mem, new_planet.max_cpus, new_planet.disk_size_mb, ship.clone()); + match r { + Err(e) => { + match e { + SolarlibError::MissingImage(_) => { + ship.download(&s)?; + return Ok(Json(s.planet(new_planet.name, new_planet.max_mem, new_planet.max_cpus, new_planet.disk_size_mb, ship.clone())?)); + }, + _ => { + return Err(ServiceError::Solarlib(e)); + } + } + }, + Ok(r) => { + let tmp = s.inhabitants()?[0].clone(); + return Ok(Json(tmp)); + } + }; +} + + +pub async fn no_planet(Path(uuid): Path<String>) -> NoneResult { + let mut s = get_star()?; + + if let Ok(p) = s.find_planet(uuid) { + p.deathstar()?; + } else { + return Err(ServiceError::NotFound); + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index c235d41..4dc78a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,12 +4,12 @@ use axum::{ response::IntoResponse, routing::{get, post}, handler::Handler, - Json, Router + Json, Router, Extension }; use serde::{Deserialize, Serialize}; use solarlib::star::Star; -use std::{net::SocketAddr, time::Duration, str::FromStr}; +use std::{net::SocketAddr, time::Duration, str::FromStr, sync::Arc}; use tower::{BoxError, ServiceBuilder}; use tower_http::trace::TraceLayer; @@ -20,6 +20,10 @@ mod errors; mod handlers; +pub struct State { + pub hw_url: String, +} + #[tokio::main] async fn main() { kankyo::init(); @@ -32,9 +36,14 @@ async fn main() { .with(tracing_subscriber::fmt::layer()) .init(); + let shared_state = Arc::new(State { + hw_url: std::env::var("HOMEWORLD_URL").expect("No Homeworld URL set"), + }); + let app = Router::new() .route("/health", get(health_check)) .route("/planets/list", get(handlers::planets::list)) + .route("/planets/new", post(handlers::planets::new_planet)) .route("/planets/:uuid", get(handlers::planets::get)) .route("/planets/:uuid/shutdown", post(handlers::planets::shutdown)) .route("/planets/:uuid/shutdown/hard", post(handlers::planets::force_shutdown)) @@ -42,6 +51,7 @@ async fn main() { .route("/planets/:uuid/pause", post(handlers::planets::pause)) .route("/planets/:uuid/reboot", post(handlers::planets::reboot)) .route("/planets/:uuid/reboot/hard", post(handlers::planets::force_reboot)) + .route("/planets/:uuid/destroy", post(handlers::planets::no_planet)) .layer( ServiceBuilder::new() .layer(HandleErrorLayer::new(|error: BoxError| async move { if error.is::<tower::timeout::error::Elapsed>() { @@ -57,6 +67,7 @@ async fn main() { .layer(TraceLayer::new_for_http()) .into_inner(), ) + .layer(Extension(shared_state)) .fallback(handler_404.into_service()); let addr = SocketAddr::from_str(std::env::var("BIND_ADDR").unwrap().as_str().into()).unwrap(); |