feat: Basic agent-client service
Some checks failed
Test / test-frontend (pull_request) Successful in 27s
Test / frontend-build (pull_request) Successful in 33s
Verify / verify-openapi-spec (pull_request) Successful in 7s
Verify / verify-generated-agent-code (pull_request) Successful in 1m7s
Verify / verify-generated-database-code (pull_request) Successful in 2m14s
Verify / verify-frontend-api-client (pull_request) Successful in 6s
Test / lint-crates (pull_request) Failing after 1m28s
Test / test-crates (pull_request) Successful in 2m40s
Test / lint-frontend (pull_request) Successful in 29s

This commit is contained in:
GW_MC
2025-12-28 17:53:27 +08:00
parent 6f395ed1ae
commit c65dc3af47
4 changed files with 170 additions and 9 deletions

82
Cargo.lock generated
View File

@@ -542,7 +542,7 @@ dependencies = [
"num-traits", "num-traits",
"serde", "serde",
"wasm-bindgen", "wasm-bindgen",
"windows-link", "windows-link 0.2.1",
] ]
[[package]] [[package]]
@@ -1709,9 +1709,11 @@ dependencies = [
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"system-configuration",
"tokio", "tokio",
"tower-service", "tower-service",
"tracing", "tracing",
"windows-registry",
] ]
[[package]] [[package]]
@@ -2468,7 +2470,7 @@ dependencies = [
"libc", "libc",
"redox_syscall", "redox_syscall",
"smallvec", "smallvec",
"windows-link", "windows-link 0.2.1",
] ]
[[package]] [[package]]
@@ -3073,8 +3075,10 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bytes", "bytes",
"encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"http-body-util", "http-body-util",
@@ -3084,6 +3088,7 @@ dependencies = [
"hyper-util", "hyper-util",
"js-sys", "js-sys",
"log", "log",
"mime",
"mime_guess", "mime_guess",
"native-tls", "native-tls",
"percent-encoding", "percent-encoding",
@@ -4193,6 +4198,27 @@ dependencies = [
"syn 2.0.111", "syn 2.0.111",
] ]
[[package]]
name = "system-configuration"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "tap" name = "tap"
version = "1.0.1" version = "1.0.1"
@@ -5008,9 +5034,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [ dependencies = [
"windows-implement", "windows-implement",
"windows-interface", "windows-interface",
"windows-link", "windows-link 0.2.1",
"windows-result", "windows-result 0.4.1",
"windows-strings", "windows-strings 0.5.1",
] ]
[[package]] [[package]]
@@ -5035,19 +5061,54 @@ dependencies = [
"syn 2.0.111", "syn 2.0.111",
] ]
[[package]]
name = "windows-link"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]] [[package]]
name = "windows-link" name = "windows-link"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-registry"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
dependencies = [
"windows-link 0.1.3",
"windows-result 0.3.4",
"windows-strings 0.4.2",
]
[[package]]
name = "windows-result"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
"windows-link 0.1.3",
]
[[package]] [[package]]
name = "windows-result" name = "windows-result"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.2.1",
]
[[package]]
name = "windows-strings"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link 0.1.3",
] ]
[[package]] [[package]]
@@ -5056,7 +5117,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.2.1",
] ]
[[package]] [[package]]
@@ -5101,7 +5162,7 @@ version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.2.1",
] ]
[[package]] [[package]]
@@ -5141,7 +5202,7 @@ version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.2.1",
"windows_aarch64_gnullvm 0.53.1", "windows_aarch64_gnullvm 0.53.1",
"windows_aarch64_msvc 0.53.1", "windows_aarch64_msvc 0.53.1",
"windows_i686_gnu 0.53.1", "windows_i686_gnu 0.53.1",
@@ -5367,6 +5428,7 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
name = "yet-another-nginx-proxy-manager" name = "yet-another-nginx-proxy-manager"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"agent_client",
"argon2", "argon2",
"async-trait", "async-trait",
"axum", "axum",
@@ -5380,9 +5442,11 @@ dependencies = [
"migration", "migration",
"mime_guess", "mime_guess",
"once_cell", "once_cell",
"reqwest",
"sea-orm", "sea-orm",
"serde", "serde",
"serde_json", "serde_json",
"tempfile",
"tokio", "tokio",
"tower", "tower",
"tower-http", "tower-http",

View File

@@ -6,6 +6,7 @@ edition = "2024"
[dependencies] [dependencies]
database = { path = "../../public/database" } database = { path = "../../public/database" }
migration = { path = "../../public/migration" } migration = { path = "../../public/migration" }
agent_client = { path = "../../public/agent-client" }
axum = { version = "0.8.7", features = ["form", "http1", "http2", "json", "matched-path", "original-uri", "query", "tokio", "tower-log", "tracing", "macros"] } axum = { version = "0.8.7", features = ["form", "http1", "http2", "json", "matched-path", "original-uri", "query", "tokio", "tower-log", "tracing", "macros"] }
axum-extra = { version = "0.12.2", features = ["cookie"] } axum-extra = { version = "0.12.2", features = ["cookie"] }
@@ -28,4 +29,7 @@ argon2 = { version = "0.5.3", features = ["std"] }
jsonwebtoken = { version = "10.2.0", features = ["rust_crypto"] } jsonwebtoken = { version = "10.2.0", features = ["rust_crypto"] }
uuid = { version = "1.19.0", features = ["v4", "serde", "fast-rng"] } uuid = { version = "1.19.0", features = ["v4", "serde", "fast-rng"] }
tower-http = { version = "0.6.8", features = ["cors"] } tower-http = { version = "0.6.8", features = ["cors"] }
reqwest = { version = "^0.12", features = ["json", "multipart", "stream"] }
[dev-dependencies]
tempfile = "3"

View File

@@ -1,3 +1,4 @@
pub mod agent_client;
pub mod auth; pub mod auth;
pub mod server_state; pub mod server_state;
pub mod settings; pub mod settings;

View File

@@ -0,0 +1,92 @@
use std::sync::Arc;
use agent_client::apis::{ApiClient, configuration::Configuration};
pub struct AgentService {
client: Arc<ApiClient>,
}
impl AgentService {
pub fn new(config: impl Into<Arc<Configuration>>) -> Self {
let client = ApiClient::new(config.into());
AgentService {
client: Arc::new(client),
}
}
pub fn get_client(&self) -> Arc<ApiClient> {
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");
}
}
}