feat: add agent module with Nginx service commands and routes

- Introduced a new agent module with commands for managing Nginx configurations.
- Implemented `NginxService` for handling reload, validation, and configuration writing.
- Added routes for status, validation, and configuration writing using Axum.
- Created necessary command files: `reload.rs`, `run.rs`, `validate.rs`, `write_config.rs`.
- Updated `Cargo.toml` and `Cargo.lock` to include new dependencies.
- Added `.gitignore` for the agent module.
- Updated `justfile` to include OpenAPI generation for the agent.
This commit is contained in:
GW_MC
2025-12-21 15:32:42 +08:00
parent 8334da8cf1
commit 4ca59d2bb6
12 changed files with 1023 additions and 3 deletions

130
apps/agent/src/routes.rs Normal file
View File

@@ -0,0 +1,130 @@
use axum::Json;
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use serde::{Deserialize, Serialize};
use serde_json::{Value, from_value};
use std::sync::Arc;
use tracing::warn;
use crate::commands::NginxService;
#[derive(Serialize)]
pub struct StatusResp {
pub ok: bool,
}
pub async fn status() -> impl IntoResponse {
let resp = StatusResp { ok: true };
(axum::http::StatusCode::OK, axum::Json(resp))
}
#[derive(Serialize)]
pub struct ValidateAndReloadResp {
pub rc: i32,
pub ro: String,
}
#[derive(Deserialize)]
pub struct ValidateBody {
config_name: String,
timestamp: u64,
}
pub async fn validate(
State(nginx_controller): State<Arc<NginxService>>,
Json(payload): Json<Value>,
) -> impl IntoResponse {
let params: ValidateBody = match from_value(payload) {
Ok(req) => req,
Err(e) => {
warn!("Invalid validate request: {}", e);
return (StatusCode::BAD_REQUEST).into_response();
}
};
let (_code, _output) = match nginx_controller
.validate(&params.config_name, params.timestamp)
.await
{
Ok(res) => res,
Err(e) => {
let resp = serde_json::json!({ "error": e.to_string() });
return (StatusCode::INTERNAL_SERVER_ERROR, axum::Json(resp)).into_response();
}
};
(axum::http::StatusCode::OK,).into_response()
}
#[derive(Deserialize)]
pub struct ValidateAndReloadBody {
config_name: String,
timestamp: u64,
}
pub async fn validate_and_reload(
State(nginx_controller): State<Arc<NginxService>>,
Json(payload): Json<Value>,
) -> impl IntoResponse {
let params: ValidateAndReloadBody = match from_value(payload) {
Ok(req) => req,
Err(e) => {
warn!("Invalid validate_and_reload request: {}", e);
return (StatusCode::BAD_REQUEST).into_response();
}
};
let (code, output) = match nginx_controller
.validate_and_reload(&params.config_name, params.timestamp)
.await
{
Ok(res) => res,
Err(e) => {
let resp = ValidateAndReloadResp {
rc: -1,
ro: e.to_string(),
};
return (StatusCode::INTERNAL_SERVER_ERROR, axum::Json(resp)).into_response();
}
};
let resp = ValidateAndReloadResp {
rc: code,
ro: output,
};
(axum::http::StatusCode::OK, axum::Json(resp)).into_response()
}
#[derive(Deserialize)]
pub struct WriteConfigBody {
config_name: String,
timestamp: u64,
content: String,
}
pub async fn write_config(
State(nginx_controller): State<Arc<NginxService>>,
Json(payload): Json<Value>,
) -> impl IntoResponse {
let body: WriteConfigBody = match from_value(payload) {
Ok(req) => req,
Err(e) => {
warn!("Invalid write_config request: {}", e);
return (StatusCode::BAD_REQUEST).into_response();
}
};
match nginx_controller
.write_config(&body.config_name, body.timestamp, &body.content)
.await
{
Ok(_) => (),
Err(e) => {
let resp = serde_json::json!({ "error": e.to_string() });
return (StatusCode::INTERNAL_SERVER_ERROR, axum::Json(resp)).into_response();
}
};
(axum::http::StatusCode::OK,).into_response()
}