feat(api): add API routes with full state wiring and integration test fixtures

- Add /api routes for agents and proxy resources

- Wire all services into ApiState in service/mod.rs

- Update route tests with all mock services
This commit is contained in:
GW_MC
2026-07-05 05:29:22 +00:00
parent a7863b9e87
commit 6f560c981b
26 changed files with 2877 additions and 4 deletions

View File

@@ -0,0 +1,62 @@
use std::sync::Arc;
use axum::{
Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use serde::Deserialize;
use tracing::error;
use crate::{
routes::api::{agents::dto::AgentInfo, error::AppError},
service::agent::{AgentService, State as AgentState, UpdateAgentRecord},
};
#[derive(Debug, Deserialize)]
pub struct UpdateAgentRequest {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub ip_address: Option<String>,
#[serde(default)]
pub state: Option<AgentState>,
#[serde(default)]
pub deployment_mode: Option<String>,
#[serde(default)]
pub labels: Option<serde_json::Value>,
}
pub async fn update_agent_handler(
State(agent_service): State<Arc<dyn AgentService>>,
Path(id): Path<uuid::Uuid>,
Json(body): Json<UpdateAgentRequest>,
) -> Result<impl IntoResponse, AppError> {
if let Some(ref name) = body.name {
if name.trim().is_empty() {
return Err(AppError::BadRequest("name must not be empty".to_string()));
}
}
let rec = UpdateAgentRecord {
name: body.name,
ip_address: body.ip_address,
state: body.state,
deployment_mode: body.deployment_mode,
labels: body.labels,
};
let agent = agent_service.update(id, &rec).await.map_err(|err| {
error!("Failed to update agent: {}", err);
AppError::InternalServerError
})?;
match agent {
Some(agent) => Ok((
StatusCode::OK,
Json(serde_json::json!({"agent": AgentInfo::from(agent)})),
)),
None => Err(AppError::NotFound),
}
}