Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3768187
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/Cargo.toml b/Cargo.toml
index fa8305e..d781616 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,28 +1,28 @@
[package]
name = "alkane"
-version = "0.1.0"
+version = "0.1.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
env_logger = "^0.10.0"
lazy_static = "^1.4.0"
limiting-factor = "^0.8.0"
log = "^0.4.17"
rocket = "^0.4.11"
rocket_codegen = "^0.4.11"
serde_yaml = "^0.9.21"
[dependencies.clap]
version = "~4.2.1"
features = ["derive"]
[dependencies.rocket_contrib]
version = "^0.4.11"
default-features = false
features = ["json"]
[dependencies.serde]
version = "^1.0.159"
features = ["derive"]
diff --git a/src/actions.rs b/src/actions.rs
index c2c28ba..a4f85f7 100644
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -1,104 +1,111 @@
// -------------------------------------------------------------
// Alkane :: Actions
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Project: Nasqueron
// License: BSD-2-Clause
// -------------------------------------------------------------
use crate::command::ServerArgs;
use crate::config::AlkaneConfig;
use crate::db::Database;
use crate::deploy::AlkaneDeployError;
use crate::deploy::DeployError;
use crate::runner::store::RecipesStore;
use crate::runner::RecipeStatus;
use crate::server::kernel::run;
// -------------------------------------------------------------
// Actions only available in CLI
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pub fn serve(args: ServerArgs, config: AlkaneConfig) {
run(config, &args.mounting_point);
}
// -------------------------------------------------------------
// Actions available both for CLI and HTTP
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-pub fn initialize(
+fn run_deployment_action(
site_name: &str,
context: Option<String>,
config: &AlkaneConfig,
+ action: &str,
) -> Result<RecipeStatus, DeployError> {
let db = Database::from_config(config).ok_or_else(|| {
- let error = AlkaneDeployError::new("Can't initialize database");
+ let error = AlkaneDeployError::new("Can't initialize database", site_name, action);
DeployError::Alkane(error)
})?;
let recipes = RecipesStore::from_config(config).ok_or_else(|| {
- let error = AlkaneDeployError::new("Can't initialize recipes store");
+ let error = AlkaneDeployError::new("Can't initialize recipes store", site_name, action);
DeployError::Alkane(error)
})?;
let site = config
.get_site(site_name, context)
- .expect("Can't get site path.");
- let status = recipes.run_recipe(&site, "init");
- db.set_initialized(&site.name);
+ .ok_or_else(|| {
+ let error = AlkaneDeployError::new("Can't resolve site path", site_name, action);
+ DeployError::Alkane(error)
+ })?;
+
+ let status = recipes.run_recipe(&site, action);
+
+ if action == "init" {
+ db.set_initialized(&site.name);
+ }
Ok(status)
}
-pub fn update(
+pub fn initialize(
site_name: &str,
context: Option<String>,
config: &AlkaneConfig,
) -> Result<RecipeStatus, DeployError> {
- let recipes = RecipesStore::from_config(config).ok_or_else(|| {
- let error = AlkaneDeployError::new("Can't initialize recipes store");
- DeployError::Alkane(error)
- })?;
+ run_deployment_action(site_name, context, config, "init")
+}
- let site = config
- .get_site(site_name, context)
- .expect("Can't get site path.");
- let status = recipes.run_recipe(&site, "update");
- Ok(status)
+pub fn update(
+ site_name: &str,
+ context: Option<String>,
+ config: &AlkaneConfig,
+) -> Result<RecipeStatus, DeployError> {
+ run_deployment_action(site_name, context, config, "update")
}
pub fn deploy(
site_name: &str,
context: Option<String>,
config: &AlkaneConfig,
) -> Result<RecipeStatus, DeployError> {
if is_present(site_name, config) {
- update(site_name, context, config)
+ run_deployment_action(site_name, context, config, "update")
} else {
- initialize(site_name, context, config)
+ run_deployment_action(site_name, context, config, "init")
}
}
pub fn is_present(site_name: &str, config: &AlkaneConfig) -> bool {
match Database::from_config(&config) {
None => false,
Some(db) => db.is_initialized(site_name),
}
}
// -------------------------------------------------------------
// Tests
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[cfg(test)]
mod tests {
use super::*;
#[test]
pub fn test_is_present() {
let config = AlkaneConfig::load().unwrap();
assert_eq!(true, is_present("foo.acme.tld", &config));
assert_eq!(false, is_present("notexisting.acme.tld", &config));
}
}
diff --git a/src/deploy.rs b/src/deploy.rs
index 1a3ca28..f5022f3 100644
--- a/src/deploy.rs
+++ b/src/deploy.rs
@@ -1,47 +1,63 @@
// -------------------------------------------------------------
// Alkane :: Deploy
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Project: Nasqueron
// License: BSD-2-Clause
// -------------------------------------------------------------
use std::error::Error;
use std::fmt::{Display, Formatter};
// -------------------------------------------------------------
// Errors during our own workflow deployment
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// Represents an error during the workflow to run a deployment
#[derive(Debug)]
pub struct AlkaneDeployError {
pub message: String,
+
+ /// The name of the site to deploy
+ pub site_name: String,
+
+ /// The deployment action, "init" or "update"
+ pub action: String,
}
impl Display for AlkaneDeployError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- write!(f, "Alkane deploy error: {}", self.message)
+ write!(f, "Can't run deployment action '{}' for site '{}': {}", self.action, self.site_name, self.message)
}
}
impl Error for AlkaneDeployError {}
impl AlkaneDeployError {
- pub fn new<S>(message: S) -> Self
+ pub fn new<S>(message: S, site_name: S, action: S) -> Self
where
S: AsRef<str>,
{
Self {
message: message.as_ref().to_string(),
+ site_name: site_name.as_ref().to_string(),
+ action: action.as_ref().to_string(),
}
}
}
// -------------------------------------------------------------
// Errors that can occur during a deployment
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[derive(Debug)]
pub enum DeployError {
Alkane(AlkaneDeployError),
}
+
+impl Display for DeployError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ match self {
+ DeployError::Alkane(error) => error.fmt(f),
+ }
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index f4fa11f..a7fd581 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,96 +1,96 @@
// -------------------------------------------------------------
// Alkane
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Project: Nasqueron
// License: BSD-2-Clause
// Description: Manage nginx and php-fpm Alkane PaaS
// -------------------------------------------------------------
#![feature(decl_macro)]
use std::process::exit;
use clap::Parser;
use crate::actions::*;
use crate::command::{AlkaneCommand, ToStatusCode};
use crate::config::AlkaneConfig;
use crate::deploy::DeployError;
use crate::runner::RecipeStatus;
// -------------------------------------------------------------
// Modules
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mod actions;
mod command;
mod config;
mod db;
mod deploy;
mod runner;
mod server;
mod services;
// -------------------------------------------------------------
// Application entry point
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fn main() {
env_logger::init();
let command = AlkaneCommand::parse(); // Will exit if argument is missing or --help/--version provided.
let config = match AlkaneConfig::load() {
Ok(config) => config,
Err(error) => {
eprintln!("Can't load configuration: {:?}", error);
exit(4);
}
};
match command {
AlkaneCommand::Server(args) => {
serve(args, config);
}
AlkaneCommand::Update(args) => {
let result = update(&args.site_name, None, &config);
deploy_exit(result);
}
AlkaneCommand::Init(args) => {
let result = initialize(&args.site_name, None, &config);
deploy_exit(result);
}
AlkaneCommand::Deploy(args) => {
let result = deploy(&args.site_name, None, &config);
deploy_exit(result);
}
AlkaneCommand::IsPresent(args) => {
let is_present = is_present(&args.site_name, &config);
if !args.quiet {
if is_present {
let path = config.get_site_path(&args.site_name).unwrap();
println!("{}", path);
} else {
eprintln!("Site is absent.")
}
}
exit(is_present.to_status_code());
}
}
}
fn deploy_exit(result: Result<RecipeStatus, DeployError>) {
match result {
Ok(status) => exit(status.to_status_code()),
Err(error) => {
- eprintln!("Can't deploy: {:?}", error);
+ eprintln!("{}", error);
exit(16);
}
}
}
diff --git a/src/server/requests.rs b/src/server/requests.rs
index e0bd3a9..ee3dd6a 100644
--- a/src/server/requests.rs
+++ b/src/server/requests.rs
@@ -1,97 +1,97 @@
// -------------------------------------------------------------
// Alkane :: Server :: Requests
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Project: Nasqueron
// License: BSD-2-Clause
// -------------------------------------------------------------
use limiting_factor::api::guards::RequestBody;
use limiting_factor::api::replies::{ApiJsonResponse, ApiResponse};
use log::{debug, info, warn};
use rocket::State;
use rocket_codegen::{get, post};
use crate::actions;
use crate::config::AlkaneConfig;
use crate::runner::RecipeStatus;
// -------------------------------------------------------------
// Monitoring
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[get("/status")]
pub fn status() -> &'static str {
"ALIVE"
}
// -------------------------------------------------------------
// 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()
}
#[post("/init/<site_name>", data = "<context>")]
pub fn init(
site_name: String,
context: RequestBody,
config: State<AlkaneConfig>,
) -> ApiJsonResponse<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(),
Err(error) => {
- warn!("Deployment error: {:?}", error);
+ warn!("{}", error);
RecipeStatus::Error.into_json_response()
}
}
}
#[post("/update/<site_name>", data = "<context>")]
pub fn update(
site_name: String,
context: RequestBody,
config: State<AlkaneConfig>,
) -> ApiJsonResponse<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(),
Err(error) => {
- warn!("Deployment error: {:?}", error);
+ warn!("{}", error);
RecipeStatus::Error.into_json_response()
}
}
}
#[post("/deploy/<site_name>", data = "<context>")]
pub fn deploy(
site_name: String,
context: RequestBody,
config: State<AlkaneConfig>,
) -> ApiJsonResponse<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(),
Err(error) => {
- warn!("Deployment error: {:?}", error);
+ warn!("{}", error);
RecipeStatus::Error.into_json_response()
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Nov 25, 07:07 (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2256919
Default Alt Text
(12 KB)
Attached To
Mode
rALK Alkane
Attached
Detach File
Event Timeline
Log In to Comment