Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F11820355
D3717.id9618.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Referenced Files
None
Subscribers
None
D3717.id9618.diff
View Options
diff --git a/Cargo.toml b/Cargo.toml
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,23 +6,24 @@
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+axum = "0.8.4"
+axum-macros = "0.5.0"
env_logger = "^0.11.5"
lazy_static = "^1.5.0"
-limiting-factor = "^0.8.0"
log = "^0.4.22"
-rocket = "^0.4.11"
-rocket_codegen = "^0.4.11"
serde_yaml = "^0.9.33"
[dependencies.clap]
version = "~4.5.17"
features = ["derive"]
-[dependencies.rocket_contrib]
-version = "^0.4.11"
-default-features = false
-features = ["json"]
-
[dependencies.serde]
version = "^1.0.210"
features = ["derive"]
+
+[dependencies.tokio]
+version = "1.47.1"
+features = [
+ "macros",
+ "rt-multi-thread",
+]
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -61,14 +61,8 @@
| Variable | Description | Default value |
|--------------------|-----------------|---------------|
-| ROCKET_PORT | Server port | 8000 |
-| ROCKET_ADDRESS | Address to bind | 0.0.0.0 |
-
-The following options allow to configure the server:
-
-| Argument | Description | Default value |
-|--------------------|-----------------|---------------|
-| --mounting-point | Mounting point | / |
+| APP_PORT | Server port | 8000 |
+| APP_ADDRESS | Address to bind | 0.0.0.0 |
Nasqueron servers expose Alkane on the port 10206, for the alkane C2H6.
@@ -140,7 +134,7 @@
Alkane is written in Rust using:
- - Rocket and Limiting Factor for the HTTP API
+ - Axum for the HTTP API
- Clap to parse arguments
- serde_yaml to deserialize configuration files
diff --git a/src/actions.rs b/src/actions.rs
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -5,7 +5,6 @@
// License: BSD-2-Clause
// -------------------------------------------------------------
-use crate::command::ServerArgs;
use crate::config::AlkaneConfig;
use crate::db::Database;
use crate::deploy::AlkaneDeployError;
@@ -18,8 +17,8 @@
// Actions only available in CLI
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-pub fn serve(args: ServerArgs, config: AlkaneConfig) {
- run(config, &args.mounting_point);
+pub async fn serve(config: AlkaneConfig) -> bool {
+ run(config).await
}
// -------------------------------------------------------------
diff --git a/src/command.rs b/src/command.rs
--- a/src/command.rs
+++ b/src/command.rs
@@ -16,7 +16,7 @@
#[clap(author="Nasqueron project", version, about="Manage Alkane PaaS", long_about=None)]
pub enum AlkaneCommand {
/// Launch an HTTP server to expose the Alkane REST API
- Server(ServerArgs),
+ Server,
/// Initialize a site
#[command(arg_required_else_help = true)]
@@ -39,12 +39,6 @@
// Subcommands arguments
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#[derive(Debug, Args)]
-pub struct ServerArgs {
- #[arg(long, default_value = "/")]
- pub mounting_point: String,
-}
-
#[derive(Debug, Args)]
pub struct DeployArgs {
/// The name of the site to deploy, using sub.domain.tld format
diff --git a/src/config.rs b/src/config.rs
--- a/src/config.rs
+++ b/src/config.rs
@@ -43,7 +43,7 @@
// the Alkane configuration file alkane.conf
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#[derive(Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize)]
pub struct AlkaneConfig {
/// The paths to the root directories used by Alkane
roots: HashMap<String, String>,
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -35,7 +35,8 @@
// Application entry point
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-fn main() {
+#[tokio::main]
+async fn main() {
env_logger::init();
let command = AlkaneCommand::parse(); // Will exit if argument is missing or --help/--version provided.
@@ -48,8 +49,10 @@
};
match command {
- AlkaneCommand::Server(args) => {
- serve(args, config);
+ AlkaneCommand::Server => {
+ let result = serve(config).await;
+
+ exit(result.to_status_code())
}
AlkaneCommand::Update(args) => {
diff --git a/src/runner/store.rs b/src/runner/store.rs
--- a/src/runner/store.rs
+++ b/src/runner/store.rs
@@ -55,7 +55,9 @@
map.insert("ALKANE_SITE_PATH".to_string(), site.path.clone());
if let Some(context) = &site.context {
- map.insert("ALKANE_SITE_CONTEXT".to_string(), context.clone());
+ if !context.is_empty() {
+ map.insert("ALKANE_SITE_CONTEXT".to_string(), context.clone());
+ }
}
map
diff --git a/src/server/kernel.rs b/src/server/kernel.rs
--- a/src/server/kernel.rs
+++ b/src/server/kernel.rs
@@ -5,8 +5,12 @@
// License: BSD-2-Clause
// -------------------------------------------------------------
-use rocket::ignite;
-use rocket_codegen::routes;
+use std::env;
+
+use axum::Router;
+use axum::routing::{get, post};
+use log::{error, info, warn};
+use tokio::net::TcpListener;
use crate::config::AlkaneConfig;
use crate::server::requests::*;
@@ -15,19 +19,51 @@
// Server entry point
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-pub fn run(config: AlkaneConfig, mounting_point: &str) {
- let routes = routes![
+fn get_socket_address() -> String {
+ let address = env::var("APP_ADDRESS")
+ .unwrap_or_else(|_| "0.0.0.0".to_string());
+
+ let port: u16 = env::var("APP_PORT")
+ .unwrap_or_else(|_| "10206".to_string())
+ .parse()
+ .unwrap_or_else(|_| {
+ warn!("Can't parse Alkane port, Using default port 10206 instead.");
+
+ 10206
+ });
+
+ format!("{}:{}", address, port)
+}
+
+pub async fn run(config: AlkaneConfig) -> bool {
+ let app = Router::new()
+
// Monitoring
- status,
+ .route("/status", get(status))
+
// Alkane API
- init,
- update,
- deploy,
- is_present,
- ];
-
- ignite()
- .manage(config)
- .mount(mounting_point, routes)
- .launch();
+ .route("/init/{site_name}", post(init))
+ .route("/update/{site_name}", post(update))
+ .route("/deploy/{site_name}", post(deploy))
+ .route("/is_present/{site_name}", get(is_present))
+ .with_state(config);
+
+ let socket_address = get_socket_address();
+
+ info!("🚀 Starting server");
+ match TcpListener::bind(&socket_address).await {
+ Ok(listener) => {
+ info!("Listening to {}", socket_address);
+ axum::serve(listener, app).await.unwrap();
+
+ true
+ }
+
+ Err(error) => {
+ error!("{}", error);
+
+ false
+ }
+ }
+
}
diff --git a/src/server/requests.rs b/src/server/requests.rs
--- a/src/server/requests.rs
+++ b/src/server/requests.rs
@@ -5,22 +5,24 @@
// License: BSD-2-Clause
// -------------------------------------------------------------
-use limiting_factor::api::guards::RequestBody;
-use limiting_factor::api::replies::{ApiJsonResponse, ApiResponse};
+use axum::extract::{Path, State};
+use axum::http::StatusCode;
+use axum::response::Json;
+
use log::{debug, info, warn};
-use rocket::State;
-use rocket_codegen::{get, post};
use crate::actions;
use crate::config::AlkaneConfig;
use crate::runner::RecipeStatus;
+type ApiErrorResult<E> = (StatusCode, Json<E>);
+type ApiResult<T> = Result<Json<T>, ApiErrorResult<T>>;
+
// -------------------------------------------------------------
// Monitoring
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#[get("/status")]
-pub fn status() -> &'static str {
+pub async fn status() -> &'static str {
"ALIVE"
}
@@ -28,70 +30,73 @@
// Alkane requests
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#[get("/is_present/<site_name>")]
-pub fn is_present(site_name: String, config: State<AlkaneConfig>) -> ApiJsonResponse<bool> {
- actions::is_present(&site_name, &config).into_json_response()
+pub async fn is_present(
+ Path(site_name): Path<String>,
+ State(config): State<AlkaneConfig>,
+) -> Json<bool> {
+ let result = actions::is_present(&*site_name, &config);
+ Json(result)
}
-#[post("/init/<site_name>", data = "<context>")]
-pub fn init(
- site_name: String,
- context: RequestBody,
- config: State<AlkaneConfig>,
-) -> ApiJsonResponse<RecipeStatus> {
+pub async fn init(
+ Path(site_name): Path<String>,
+ State(config): State<AlkaneConfig>,
+ context: String,
+) -> ApiResult<RecipeStatus> {
info!("Deploying {}", &site_name);
-
- let context = context.into_optional_string();
debug!("Context: {:?}", &context);
- match actions::initialize(&site_name, context, &config) {
- Ok(status) => status.into_json_response(),
+ match actions::initialize(&*site_name, Some(context), &config) {
+ Ok(status) => Ok(Json(status)),
Err(error) => {
warn!("{}", error);
- RecipeStatus::Error.into_json_response()
+ Err((
+ StatusCode::INTERNAL_SERVER_ERROR,
+ Json(RecipeStatus::Error)
+ ))
}
}
}
-#[post("/update/<site_name>", data = "<context>")]
-pub fn update(
- site_name: String,
- context: RequestBody,
- config: State<AlkaneConfig>,
-) -> ApiJsonResponse<RecipeStatus> {
+pub async fn update(
+ Path(site_name): Path<String>,
+ State(config): State<AlkaneConfig>,
+ context: String,
+) -> ApiResult<RecipeStatus> {
info!("Deploying {}", &site_name);
-
- let context = context.into_optional_string();
debug!("Context: {:?}", &context);
- match actions::update(&site_name, context, &config) {
- Ok(status) => status.into_json_response(),
+ match actions::update(&*site_name, Some(context), &config) {
+ Ok(status) => Ok(Json(status)),
Err(error) => {
warn!("{}", error);
- RecipeStatus::Error.into_json_response()
+ Err((
+ StatusCode::INTERNAL_SERVER_ERROR,
+ Json(RecipeStatus::Error)
+ ))
}
}
}
-#[post("/deploy/<site_name>", data = "<context>")]
-pub fn deploy(
- site_name: String,
- context: RequestBody,
- config: State<AlkaneConfig>,
-) -> ApiJsonResponse<RecipeStatus> {
+pub async fn deploy(
+ Path(site_name): Path<String>,
+ State(config): State<AlkaneConfig>,
+ context: String,
+) -> ApiResult<RecipeStatus> {
info!("Deploying {}", &site_name);
-
- let context = context.into_optional_string();
debug!("Context: {:?}", &context);
- match actions::deploy(&site_name, context, &config) {
- Ok(status) => status.into_json_response(),
+ match actions::deploy(&*site_name, Some(context), &config) {
+ Ok(status) => Ok(Json(status)),
Err(error) => {
warn!("{}", error);
- RecipeStatus::Error.into_json_response()
+ Err((
+ StatusCode::INTERNAL_SERVER_ERROR,
+ Json(RecipeStatus::Error)
+ ))
}
}
}
diff --git a/support/freebsd/rc.d/alkane b/support/freebsd/rc.d/alkane
--- a/support/freebsd/rc.d/alkane
+++ b/support/freebsd/rc.d/alkane
@@ -73,7 +73,7 @@
alkane_log_enable="NO"
fi
-alkane_env="${alkane_env} ROCKET_SECRET=$(openssl rand -base64 32) ROCKET_PORT=${alkane_port} ROCKET_ADDRESS=${alkane_address} ${alkane_env}"
+alkane_env="${alkane_env} APP_PORT=${alkane_port} APP_ADDRESS=${alkane_address} ${alkane_env}"
pidfile=/var/run/alkane.pid
procname="/usr/local/bin/alkane"
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Sep 25, 23:06 (22 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3016330
Default Alt Text
D3717.id9618.diff (11 KB)
Attached To
Mode
D3717: Port Alkane HTTP server to axum
Attached
Detach File
Event Timeline
Log In to Comment