use std::sync::Arc; use agent_client::apis::{ApiClient, configuration::Configuration}; use tracing::warn; use crate::configs::agent::AgentSettings; pub struct AgentService { client: Arc, } impl From for Configuration { fn from(settings: AgentSettings) -> Self { let mut config = Configuration::default(); let mut builder = reqwest::Client::builder(); let url = settings.socket_path; if url.starts_with("unix://") { builder = builder.unix_socket(url.to_string()); config.client = builder.build().expect("Failed to build reqwest client"); } else { warn!("AgentSettings contains a non-unix socket path: {}", url); config.base_path = url; } config } } impl AgentService { pub fn new(config: impl Into>) -> Self { let client = ApiClient::new(config.into()); AgentService { client: Arc::new(client), } } #[allow(dead_code)] pub fn get_client(&self) -> Arc { Arc::clone(&self.client) } } #[cfg(test)] mod tests { use super::*; use agent_client::{ apis::{Api, nginx_agent_api::StatusSuccess}, models::StatusResp, }; use axum::{http::StatusCode, response::Json}; use std::time::Duration; use tempfile::tempdir; use tokio::time::sleep; #[test] fn test_agent_service_creation() { let config = Configuration::default(); let service = AgentService::new(config); let client = service.get_client(); assert!(Arc::ptr_eq(&client, &service.client)); } #[tokio::test] async fn test_agent_socket_support() { // create temporary socket path let dir = tempdir().expect("Failed to create temp dir"); let socket_path = dir.path().join("agent.sock"); // create axum app with a simple /status route let app = axum::Router::new().route( "/status", axum::routing::get(|| async { let result: (StatusCode, StatusResp) = (StatusCode::OK, StatusResp { ok: true }); (result.0, Json(result.1)) }), ); // bind tokio unix listener and serve in background let listener = tokio::net::UnixListener::bind(&socket_path).expect("Failed to bind to unix socket"); let server_fut = axum::serve::serve(listener, app); let _srv = tokio::spawn(async move { let _ = server_fut.await; }); // give server a moment to start sleep(Duration::from_millis(50)).await; let client: ApiClient = ApiClient::new(Arc::new(Configuration { base_path: "http://localhost".to_string(), client: reqwest::Client::builder() .unix_socket(socket_path.clone()) .build() .expect("Failed to build reqwest client"), ..Default::default() })); let res = client .nginx_agent_api() .status() .await .expect("Failed to get status"); let body = res.entity.expect("Response entity is missing"); assert!(res.status.is_success()); if let StatusSuccess::Status200(body) = body { assert!(body.ok); } else { panic!("Unexpected response body"); } } }