1pub mod audit;
8pub mod auth;
9pub mod handlers;
10pub mod rbac;
11pub mod routes;
12pub mod models;
14pub mod prometheus_client;
15pub mod time_travel_handlers;
16
17pub use models::{RequestLog, RouteInfo, ServerStatus, SystemInfo};
18pub use routes::create_admin_router;
19
20use std::net::SocketAddr;
21
22#[allow(clippy::too_many_arguments)]
41pub async fn start_admin_server(
42 addr: SocketAddr,
43 http_server_addr: Option<SocketAddr>,
44 ws_server_addr: Option<SocketAddr>,
45 grpc_server_addr: Option<SocketAddr>,
46 graphql_server_addr: Option<SocketAddr>,
47 api_enabled: bool,
48 prometheus_url: String,
49 chaos_api_state: Option<std::sync::Arc<mockforge_chaos::api::ChaosApiState>>,
50 latency_injector: Option<
51 std::sync::Arc<tokio::sync::RwLock<mockforge_core::latency::LatencyInjector>>,
52 >,
53 mockai: Option<
54 std::sync::Arc<tokio::sync::RwLock<mockforge_core::intelligent_behavior::MockAI>>,
55 >,
56 continuum_config: Option<mockforge_core::ContinuumConfig>,
57 virtual_clock: Option<std::sync::Arc<mockforge_core::VirtualClock>>,
58 recorder: Option<std::sync::Arc<mockforge_recorder::Recorder>>,
59 federation: Option<std::sync::Arc<mockforge_federation::Federation>>,
60 vbr_engine: Option<std::sync::Arc<mockforge_vbr::VbrEngine>>,
61) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
62 let app = create_admin_router(
63 http_server_addr,
64 ws_server_addr,
65 grpc_server_addr,
66 graphql_server_addr,
67 api_enabled,
68 addr.port(),
69 prometheus_url,
70 chaos_api_state,
71 latency_injector,
72 mockai,
73 continuum_config,
74 virtual_clock,
75 recorder,
76 federation,
77 vbr_engine,
78 );
79
80 tracing::info!("Starting MockForge Admin UI on {}", addr);
81
82 let listener = tokio::net::TcpListener::bind(addr).await.map_err(|e| {
83 format!(
84 "Failed to bind Admin UI server to port {}: {}\n\
85 Hint: The port may already be in use. Try using a different port with --admin-port or check if another process is using this port with: lsof -i :{} or netstat -tulpn | grep {}",
86 addr.port(), e, addr.port(), addr.port()
87 )
88 })?;
89
90 axum::serve(listener, app).await?;
91
92 Ok(())
93}
94
95include!(concat!(env!("OUT_DIR"), "/ui_content.rs"));
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_get_admin_html() {
104 let html = get_admin_html();
105 assert!(!html.is_empty());
106 assert!(html.contains("<!DOCTYPE html>") || html.contains("<html"));
107 }
108
109 #[test]
110 fn test_get_admin_css() {
111 let _css = get_admin_css();
112 }
114
115 #[test]
116 fn test_get_admin_js() {
117 let _js = get_admin_js();
118 }
120}