8000 Review architecture, set up web backend server with routes by damien-mathieu1 · Pull Request #3 · Nephelios/nephelios · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Review architecture, set up web backend server with routes #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
917 changes: 917 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ edition = "2021"
tokio = { version = "1", features = ["full"] }
uuid = { version = "0.8", features = ["v4"] }
dirs = "*"
warp = "*"
serde_json = "*"

[[bin]]
name = "nephelios"
Expand Down
30 changes: 30 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
```
project/
├── src/
│ ├── main.rs # Entry point
│ ├── routes.rs # Define HTTP routes
│ ├── services/
│ │ ├── app\*service.rs # Application lifecycle management
│ │ ├── nginx_service.rs # NGINX configuration management
│ │ ├── helpers/
│ │ │ ├── github_helper.rs # GitHub-related utilities
│ │ │ ├── docker_helper.rs # Docker-related utilities
│ │ │ ├── nginx_helper.rs # NGINX helper functions
│ │ │ └── storage_helper.rs # Database access layer
│ └── models/
│ ├── app_config.rs # Struct definitions (e.g., AppConfig)
│ └── response.rs # Response structures
├── nginx/
│ ├── nginx.conf.template # Template for dynamic NGINX configuration
│ ├── conf.d/
│ │ └── \*.conf # Per-app configurations
├── tests/ # Integration and unit tests
│ ├── test_app_creation.rs # Test creating apps
│ ├── test_routing.rs # Test NGINX routing
│ └── test_docker.rs # Test Docker integration
├── Cargo.toml # Dependencies and project config
├── README.md # Documentation
└── .env # Environment variables
```

This is the architecture we tend to achieve
73 changes: 26 additions & 47 deletions src/main.rs
8000
Original file line number Diff line numberDiff line change
@@ -1,54 +1,33 @@
mod helpers {
pub mod docker_helper;
pub mod github_helper;
}
use crate::helpers::docker_helper as docker;
use crate::helpers::github_helper as github;
mod routes;
mod services;

use crate::routes::{create_app_route, health_check_route};
use warp::Filter;

/// Orchestrates the entire deployment pipeline:
/// 1. Clones a GitHub repository.
/// 2. Generates and writes a Dockerfile.
/// 3. Builds a Docker image.
/// 4. Runs a Docker container.
/// 5. Cleans up the temporary directory.
/// Entry point for the application.
///
/// # Arguments
/// * `github_url` - The URL of the GitHub repository to clone.
/// * `app_type` - The type of the application (e.g., "nodejs", "python").
/// * `app_name` - The name of the application, used for image and container tagging.
/// Initializes and starts the Warp server. The server listens on `127.0.0.1:3030`
/// and provides the following routes:
/// - `/create` (POST): Handles app creation requests. Expects a JSON body with app details.
/// - `/health` (GET): Provides a simple health check endpoint to verify the server's status.
///
/// # Returns
/// `Ok(())` on success or `Err(String)` with an error message on failure.
fn pipeline(github_url: &str, app_type: &str, app_name: &str) -> Result<(), String> {
let temp_dir = github::create_temp_dir(app_name)?;

let target_dir = format!("{}/{}", temp_dir.display(), uuid::Uuid::new_v4());

// Step 1: Clone Repository
github::clone_repo(github_url, &target_dir)?;

// Step 2: Generate Dockerfile
docker::generate_and_write_dockerfile(app_type, &target_dir)?;

// Step 3: Build Docker Image
docker::build_image(app_name, &target_dir)?;

// Step 4: Run Docker Container
docker::create_and_run_container(app_name)?;

// Step 5: Cleanup
github::remove_temp_dir(&temp_dir)?;

Ok(())
}

/// Combines the routes using Warp's `or` filter and serves them.
///
/// # Example
///
/// To start the server, run the application and use the following curl commands:
/// ```sh
/// # Health check
/// curl http://127.0.0.1:3030/health
///
/// # App creation (example)
/// curl -X POST http://127.0.0.1:3030/create \
/// -H "Content-Type: application/json" \
/// -d '{"app_name": "my-app", "app_type": "nodejs", "github_url": "https://github.com/user/repo"}'
/// ```
#[tokio::main]
async fn main() {
let github_url = "https://github.com/rat9615/simple-nodejs-app";
let app_type = "nodejs";
let app_name = "my-app";
let api_routes = create_app_route().or(health_check_route());

if let Err(e) = pipeline(github_url, app_type, app_name) {
eprintln!("Pipeline failed: {}", e);
}
warp::serve(api_routes).run(([127, 0, 0, 1], 3030)).await;
}
81 changes: 81 additions & 0 deletions src/routes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use warp::Filter;

/// Creates the route for app creation.
///
/// This route listens for POST requests at the `/create` path and expects a JSON body.
/// The JSON body should contain the following keys:
/// - `app_name`: The name of the application (default: "default-app").
/// - `app_type`: The type of the application (e.g., "nodejs", default: "nodejs").
/// - `github_url`: The GitHub URL for the application repository (required).
///
/// Returns a boxed Warp filter that handles app creation requests.
pub fn create_app_route() -> warp::filters::BoxedFilter<(impl warp::Reply,)> {
warp::post()
.and(warp::path("create"))
.and(warp::body::json()) // Expect JSON body
.and_then(handle_create_app)
.boxed()
}

/// Creates the route for health checks.
///
/// This route listens for GET requests at the `/health` path.
/// It is used to verify the server's status and returns a JSON response "OK".
///
/// Returns a boxed Warp filter that handles health check requests.
pub fn health_check_route() -> warp::filters::BoxedFilter<(impl warp::Reply,)> {
warp::get()
.and(warp::path("health"))
.map(|| warp::reply::json(&"OK"))
.boxed()
}

/// Handles the app creation logic.
///
/// Extracts `app_name`, `app_type`, and `github_url` from the JSON body.
/// If `github_url` is missing or empty, it returns a 400 Bad Request response.
/// Otherwise, it returns a 201 Created response indicating the app was created.
///
/// # Arguments
///
/// * `body` - The JSON body received in the POST request.
///
/// # Returns
///
/// A result containing a Warp reply or a Warp rejection.
async fn handle_create_app(body: serde_json::Value) -> Result<impl warp::Reply, warp::Rejection> {
// Extract values safely using Option and Result handling
let app_name = body
.get("app_name")
.and_then(|v| v.as_str())
.unwrap_or("default-app");
let app_type = body
.get("app_type")
.and_then(|v| v.as_str())
.unwrap_or("nodejs");
let github_url = body.get("github_url").and_then(|v| v.as_str());

if let Some(github_url) = github_url {
if github_url.is_empty() {
return Ok(warp::reply::with_status(
"GitHub URL is required".to_string(),
warp::http::StatusCode::BAD_REQUEST,
));
}

let string_response = format!(
"Created app: {} of type: {} with GitHub URL: {}",
app_name, app_type, github_url
);

Ok(warp::reply::with_status(
string_response,
warp::http::StatusCode::CREATED,
))
} else {
Ok(warp::reply::with_status(
"GitHub URL is required".to_string(),
warp::http::StatusCode::BAD_REQUEST,
))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ pub fn generate_and_write_dockerfile(app_type: &str, app_path: &str) -> Result<(
CMD ["python", "app.py"]
"#
}
_ => {
return Err(format!("Unsupported app type: {}", app_type));
}
_ => return Err(format!("Unsupported app type: {}", app_type)),
};

let dockerfile_path = Path::new(app_path).join("Dockerfile");
Expand Down
9E81
File renamed without changes.
2 changes: 2 additions & 0 deletions src/services/helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod docker_helper;
pub mod github_helper;
1 change: 1 addition & 0 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod helpers;
Loading
0