feature/proxy-service #14

Merged
GW_MC merged 8 commits from feature/proxy-service into master 2026-01-12 11:56:39 +08:00
17 changed files with 136 additions and 66 deletions
Showing only changes of commit 7ae76f622c - Show all commits

View File

@@ -30,7 +30,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{location, upstream, upstream_target}; use database::generated::entities::{location, upstream, upstream_target};
@@ -105,11 +105,13 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(vec![vec![loc_model.clone()]]) .append_query_results(vec![vec![loc_model.clone()]])
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());
@@ -213,7 +215,7 @@ pub async fn create_location(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;

View File

@@ -30,7 +30,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{location, proxy_host, upstream, upstream_target}; use database::generated::entities::{location, proxy_host, upstream, upstream_target};
@@ -125,12 +125,14 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(vec![vec![ph_model.clone()]]) .append_query_results(vec![vec![ph_model.clone()]])
.append_query_results(vec![vec![loc_model.clone()]]) .append_query_results(vec![vec![loc_model.clone()]])
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());
@@ -293,13 +295,13 @@ pub async fn create_proxy(
let mut tx = state.database_connection.begin().await?; let mut tx = state.database_connection.begin().await?;
let info = proxy_service let info = proxy_service
.create_proxy(create_info, Some(&mut tx)) .create_proxy(create_info, &Some(&mut tx))
.await?; .await?;
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;

View File

@@ -46,9 +46,9 @@ pub async fn get_proxy_list(
include_upstream: true, include_upstream: true,
filter_by_enabled: false, filter_by_enabled: false,
}), }),
None, &None,
), ),
svc.get_total_proxies(None, None), svc.get_total_proxies(None, &None),
); );
let proxies = proxies_res?; let proxies = proxies_res?;
@@ -271,11 +271,11 @@ pub async fn get_proxy(
include_upstream: true, include_upstream: true,
filter_by_enabled: false, filter_by_enabled: false,
}), }),
None, &None,
) )
.await? .await?
} else { } else {
svc.get_proxy(proxy_id, None, None).await? svc.get_proxy(proxy_id, None, &None).await?
}; };
Ok(Json(info.into())) Ok(Json(info.into()))
} }

View File

@@ -37,7 +37,7 @@ pub async fn remove_location(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -50,7 +50,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{location, upstream, upstream_target}; use database::generated::entities::{location, upstream, upstream_target};
@@ -122,6 +122,7 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(vec![vec![existing.clone()]]) .append_query_results(vec![vec![existing.clone()]])
@@ -131,6 +132,7 @@ mod tests {
}]) }])
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -34,11 +34,11 @@ pub async fn remove_proxy(
let svc = &state.service.nginx.get_proxy_service(); let svc = &state.service.nginx.get_proxy_service();
let mut tx = state.database_connection.begin().await?; let mut tx = state.database_connection.begin().await?;
svc.delete_proxy(proxy_id, Some(&mut tx)).await?; svc.delete_proxy(proxy_id, &Some(&mut tx)).await?;
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -51,7 +51,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockExecResult}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockExecResult, MockRow};
use database::generated::entities::{proxy_host, upstream, upstream_target}; use database::generated::entities::{proxy_host, upstream, upstream_target};
@@ -125,6 +125,7 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(vec![vec![existing.clone()]]) .append_query_results(vec![vec![existing.clone()]])
@@ -140,6 +141,7 @@ mod tests {
]) ])
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -34,7 +34,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{location, upstream, upstream_target}; use database::generated::entities::{location, upstream, upstream_target};
@@ -111,12 +111,14 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(first) .append_query_results(first)
.append_query_results(second) .append_query_results(second)
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());
@@ -210,7 +212,7 @@ pub async fn update_location(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;

View File

@@ -26,7 +26,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{proxy_host, upstream, upstream_target}; use database::generated::entities::{proxy_host, upstream, upstream_target};
@@ -105,12 +105,14 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(first) .append_query_results(first)
.append_query_results(second) .append_query_results(second)
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());
@@ -213,11 +215,11 @@ pub async fn update_proxy(
let update: UpdateProxyHostInfo = payload.into(); let update: UpdateProxyHostInfo = payload.into();
let mut tx = state.database_connection.begin().await?; let mut tx = state.database_connection.begin().await?;
let info = svc.update_proxy(proxy_id, update, Some(&mut tx)).await?; let info = svc.update_proxy(proxy_id, update, &Some(&mut tx)).await?;
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;

View File

@@ -131,7 +131,7 @@ pub async fn create_upstream(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -145,7 +145,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{upstream, upstream_target}; use database::generated::entities::{upstream, upstream_target};
@@ -204,6 +204,7 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
// service will likely perform an insert and then query to return created models // service will likely perform an insert and then query to return created models
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
@@ -213,6 +214,7 @@ mod tests {
// `find_with_related` returns rows of `(upstream, Option<target>)` which // `find_with_related` returns rows of `(upstream, Option<target>)` which
// the mock DB expects as `(Model, Option<Model>)` per row. // the mock DB expects as `(Model, Option<Model>)` per row.
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -86,7 +86,7 @@ pub async fn add_upstream_target(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -100,7 +100,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{upstream, upstream_target}; use database::generated::entities::{upstream, upstream_target};
@@ -158,6 +158,7 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
// configure mock agent to return an error on apply // configure mock agent to return an error on apply
let mut mock = MockAgentService::new(); let mut mock = MockAgentService::new();
@@ -175,6 +176,7 @@ mod tests {
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(vec![vec![target_model.clone()]]) .append_query_results(vec![vec![target_model.clone()]])
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let program_settings = ProgramSettings::mock(); let program_settings = ProgramSettings::mock();
@@ -235,11 +237,13 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(vec![vec![target_model.clone()]]) .append_query_results(vec![vec![target_model.clone()]])
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -40,7 +40,7 @@ pub async fn remove_upstream(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -54,7 +54,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockExecResult}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockExecResult, MockRow};
use database::generated::entities::{upstream, upstream_target}; use database::generated::entities::{upstream, upstream_target};
@@ -109,6 +109,7 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(vec![vec![existing.clone()]]) .append_query_results(vec![vec![existing.clone()]])
@@ -124,6 +125,7 @@ mod tests {
]) ])
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(existing.clone(), Some(target_model.clone()))]]) .append_query_results(vec![vec![(existing.clone(), Some(target_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -40,7 +40,7 @@ pub async fn remove_upstream_target(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -54,7 +54,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockExecResult}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockExecResult, MockRow};
use database::generated::entities::{upstream, upstream_target}; use database::generated::entities::{upstream, upstream_target};
@@ -110,6 +110,7 @@ mod tests {
created_at: chrono::Utc::now(), created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(), updated_at: chrono::Utc::now(),
}; };
let dummy_row: Vec<MockRow> = vec![];
let first: Vec<Vec<upstream_target::Model>> = vec![vec![current_model.clone()]]; let first: Vec<Vec<upstream_target::Model>> = vec![vec![current_model.clone()]];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
@@ -120,6 +121,7 @@ mod tests {
}]) }])
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
.append_query_results(vec![vec![(up_model.clone(), Some(current_model.clone()))]]) .append_query_results(vec![vec![(up_model.clone(), Some(current_model.clone()))]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -78,7 +78,7 @@ pub async fn update_upstream(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -92,7 +92,7 @@ mod tests {
use axum::http::StatusCode; use axum::http::StatusCode;
use axum_test::TestServer; use axum_test::TestServer;
use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase}; use sea_orm::{DatabaseBackend, DatabaseConnection, MockDatabase, MockRow};
use database::generated::entities::{upstream, upstream_target}; use database::generated::entities::{upstream, upstream_target};
@@ -152,6 +152,7 @@ mod tests {
let up_model = current_model.clone(); let up_model = current_model.clone();
let first: Vec<Vec<upstream::Model>> = vec![vec![current_model.clone()]]; let first: Vec<Vec<upstream::Model>> = vec![vec![current_model.clone()]];
let second: Vec<Vec<upstream::Model>> = vec![vec![updated_model.clone()]]; let second: Vec<Vec<upstream::Model>> = vec![vec![updated_model.clone()]];
let dummy_row: Vec<MockRow> = vec![];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(first) .append_query_results(first)
.append_query_results(second) .append_query_results(second)
@@ -160,6 +161,7 @@ mod tests {
up_model.clone(), up_model.clone(),
Option::<upstream_target::Model>::None, Option::<upstream_target::Model>::None,
)]]) )]])
.append_query_results(vec![dummy_row])
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -70,7 +70,7 @@ pub async fn update_upstream_target(
state state
.service .service
.nginx .nginx
.regenerate_and_apply_config(state.service.agent_client.clone(), Some(&mut tx)) .regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
.await?; .await?;
tx.commit().await?; tx.commit().await?;
@@ -165,11 +165,14 @@ mod tests {
// additional query result for regenerate_and_apply_config -> generate_config // additional query result for regenerate_and_apply_config -> generate_config
let third: Vec<Vec<(upstream::Model, Option<upstream_target::Model>)>> = let third: Vec<Vec<(upstream::Model, Option<upstream_target::Model>)>> =
vec![vec![(up_model.clone(), Some(updated_model.clone()))]]; vec![vec![(up_model.clone(), Some(updated_model.clone()))]];
// placeholder for other queries called by regenerate_and_apply_config
let fourth: Vec<Vec<upstream::Model>> = vec![vec![]];
let db = MockDatabase::new(DatabaseBackend::Sqlite) let db = MockDatabase::new(DatabaseBackend::Sqlite)
.append_query_results(first) .append_query_results(first)
.append_query_results(second) .append_query_results(second)
.append_query_results(third) .append_query_results(third)
.append_query_results(fourth)
.into_connection(); .into_connection();
let router = get_router_with_state(db.clone()); let router = get_router_with_state(db.clone());

View File

@@ -81,12 +81,13 @@ impl NginxService {
pub async fn generate_config( pub async fn generate_config(
&self, &self,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<String, ServiceError> { ) -> Result<String, ServiceError> {
let mut builder = NginxConfigBuilder::default(); let mut builder = NginxConfigBuilder::default();
self.upstream_service self.upstream_service
.generate_config(&mut builder, tx) .generate_config(&mut builder, tx)
.await?; .await?;
self.proxy_service.generate_config(&mut builder, tx).await?;
builder.to_nginx_config(None) builder.to_nginx_config(None)
} }
@@ -94,7 +95,7 @@ impl NginxService {
pub async fn regenerate_and_apply_config( pub async fn regenerate_and_apply_config(
&self, &self,
agent: Arc<dyn AgentService>, agent: Arc<dyn AgentService>,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> { ) -> Result<(), ServiceError> {
let config = self.generate_config(tx).await?; let config = self.generate_config(tx).await?;

View File

@@ -1,4 +1,7 @@
use crate::{errors::service_error::ServiceError, services::nginx::info::upstream::UpstreamInfo}; use crate::{
errors::service_error::ServiceError,
services::nginx::info::{proxy_host::ProxyHostInfo, upstream::UpstreamInfo},
};
pub const INDENT_SIZE: usize = 2; pub const INDENT_SIZE: usize = 2;
@@ -9,6 +12,7 @@ pub trait NginxConfigProvider {
#[derive(Default)] #[derive(Default)]
pub struct NginxConfigBuilder { pub struct NginxConfigBuilder {
upstreams: Vec<UpstreamInfo>, upstreams: Vec<UpstreamInfo>,
proxy_hosts: Vec<ProxyHostInfo>,
} }
impl NginxConfigBuilder { impl NginxConfigBuilder {
@@ -21,6 +25,16 @@ impl NginxConfigBuilder {
self.add_upstream(upstream); self.add_upstream(upstream);
} }
} }
pub fn add_proxy_host(&mut self, proxy_host: ProxyHostInfo) {
self.proxy_hosts.push(proxy_host);
}
pub fn add_proxy_hosts(&mut self, proxy_hosts: Vec<ProxyHostInfo>) {
for proxy_host in proxy_hosts {
self.add_proxy_host(proxy_host);
}
}
} }
impl NginxConfigProvider for NginxConfigBuilder { impl NginxConfigProvider for NginxConfigBuilder {
@@ -35,6 +49,10 @@ impl NginxConfigProvider for NginxConfigBuilder {
config.push_str(&upstream.to_nginx_config(indent)?); config.push_str(&upstream.to_nginx_config(indent)?);
} }
for proxy_host in &self.proxy_hosts {
config.push('\n');
config.push_str(&proxy_host.to_nginx_config(indent)?);
}
// TODO: Add other sections like servers, locations, etc. // TODO: Add other sections like servers, locations, etc.
// trailing newline for file ending // trailing newline for file ending
config.push('\n'); config.push('\n');

View File

@@ -11,7 +11,10 @@ use database::generated::entities::{location, proxy_host};
use crate::{ use crate::{
errors::service_error::ServiceError, errors::service_error::ServiceError,
helpers::database::PaginationFilter, helpers::database::PaginationFilter,
services::nginx::info::proxy_host::{ProxyHostCreateInfo, ProxyHostInfo, UpdateProxyHostInfo}, services::nginx::{
builder::NginxConfigBuilder,
info::proxy_host::{ProxyHostCreateInfo, ProxyHostInfo, UpdateProxyHostInfo},
},
with_conn, with_conn,
}; };
@@ -20,35 +23,40 @@ pub trait ProxyService: Send + Sync {
async fn create_proxy( async fn create_proxy(
&self, &self,
create_info: ProxyHostCreateInfo, create_info: ProxyHostCreateInfo,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError>; ) -> Result<ProxyHostInfo, ServiceError>;
async fn get_total_proxies( async fn get_total_proxies(
&self, &self,
options: Option<ProxyTotalCountOptions>, options: Option<ProxyTotalCountOptions>,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<u64, ServiceError>; ) -> Result<u64, ServiceError>;
async fn get_proxies( async fn get_proxies(
&self, &self,
pagination: Option<PaginationFilter>, pagination: Option<PaginationFilter>,
options: Option<ProxyHostListOptions>, options: Option<ProxyHostListOptions>,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<Vec<ProxyHostInfo>, ServiceError>; ) -> Result<Vec<ProxyHostInfo>, ServiceError>;
async fn get_proxy( async fn get_proxy(
&self, &self,
proxy_id: uuid::Uuid, proxy_id: uuid::Uuid,
options: Option<ProxyHostGetOptions>, options: Option<ProxyHostGetOptions>,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError>; ) -> Result<ProxyHostInfo, ServiceError>;
async fn update_proxy( async fn update_proxy(
&self, &self,
proxy_id: uuid::Uuid, proxy_id: uuid::Uuid,
update: UpdateProxyHostInfo, update: UpdateProxyHostInfo,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError>; ) -> Result<ProxyHostInfo, ServiceError>;
async fn delete_proxy( async fn delete_proxy(
&self, &self,
proxy_id: uuid::Uuid, proxy_id: uuid::Uuid,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError>;
async fn generate_config(
&self,
builder: &mut NginxConfigBuilder,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError>; ) -> Result<(), ServiceError>;
} }
@@ -78,18 +86,18 @@ impl ProxyService for ProxyServiceImpl {
async fn create_proxy( async fn create_proxy(
&self, &self,
create_info: ProxyHostCreateInfo, create_info: ProxyHostCreateInfo,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError> { ) -> Result<ProxyHostInfo, ServiceError> {
let (proxy_host, location_models): (proxy_host::ActiveModel, Vec<location::ActiveModel>) = let (proxy_host, location_models): (proxy_host::ActiveModel, Vec<location::ActiveModel>) =
create_info.into(); create_info.into();
let mut maybe_owned_tx: Option<DatabaseTransaction> = None; let owned_tx = match tx {
let tx_ref: Option<&mut DatabaseTransaction> = if let Some(tx) = tx { Some(_) => None,
Some(tx) None => Some(self.connection.begin().await.map_err(ServiceError::from)?),
} else {
maybe_owned_tx = Some(self.connection.begin().await?);
maybe_owned_tx.as_mut()
}; };
let tx_ref = owned_tx.as_ref().or(tx.as_deref());
let r = with_conn!(&*self.connection, tx_ref, conn, { let r = with_conn!(&*self.connection, tx_ref, conn, {
let inserted_proxy = proxy_host.insert(*conn).await?; let inserted_proxy = proxy_host.insert(*conn).await?;
let mut inserted_location_models: Vec<location::Model> = let mut inserted_location_models: Vec<location::Model> =
@@ -103,16 +111,13 @@ impl ProxyService for ProxyServiceImpl {
(inserted_proxy, inserted_location_models) (inserted_proxy, inserted_location_models)
}); });
if let Some(t) = maybe_owned_tx.take() {
t.commit().await?;
}
Ok(r.into()) Ok(r.into())
} }
async fn get_total_proxies( async fn get_total_proxies(
&self, &self,
_options: Option<ProxyTotalCountOptions>, _options: Option<ProxyTotalCountOptions>,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<u64, ServiceError> { ) -> Result<u64, ServiceError> {
#[derive(Debug, FromQueryResult)] #[derive(Debug, FromQueryResult)]
struct CountResult { struct CountResult {
@@ -133,7 +138,7 @@ impl ProxyService for ProxyServiceImpl {
&self, &self,
pagination: Option<PaginationFilter>, pagination: Option<PaginationFilter>,
options: Option<ProxyHostListOptions>, options: Option<ProxyHostListOptions>,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<Vec<ProxyHostInfo>, ServiceError> { ) -> Result<Vec<ProxyHostInfo>, ServiceError> {
let r = with_conn!(&*self.connection, tx, conn, { let r = with_conn!(&*self.connection, tx, conn, {
let mut find_query = proxy_host::Entity::find(); let mut find_query = proxy_host::Entity::find();
@@ -177,7 +182,7 @@ impl ProxyService for ProxyServiceImpl {
&self, &self,
proxy_id: uuid::Uuid, proxy_id: uuid::Uuid,
options: Option<ProxyHostGetOptions>, options: Option<ProxyHostGetOptions>,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError> { ) -> Result<ProxyHostInfo, ServiceError> {
let r: ProxyHostInfo = with_conn!(&*self.connection, tx, conn, { let r: ProxyHostInfo = with_conn!(&*self.connection, tx, conn, {
let find_query = proxy_host::Entity::find_by_id(proxy_id) let find_query = proxy_host::Entity::find_by_id(proxy_id)
@@ -217,7 +222,7 @@ impl ProxyService for ProxyServiceImpl {
&self, &self,
proxy_id: uuid::Uuid, proxy_id: uuid::Uuid,
update: UpdateProxyHostInfo, update: UpdateProxyHostInfo,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError> { ) -> Result<ProxyHostInfo, ServiceError> {
let current_model = with_conn!(&*self.connection, tx, conn, { let current_model = with_conn!(&*self.connection, tx, conn, {
proxy_host::Entity::find_by_id(proxy_id) proxy_host::Entity::find_by_id(proxy_id)
@@ -239,7 +244,7 @@ impl ProxyService for ProxyServiceImpl {
async fn delete_proxy( async fn delete_proxy(
&self, &self,
proxy_id: uuid::Uuid, proxy_id: uuid::Uuid,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> { ) -> Result<(), ServiceError> {
let model = with_conn!(&*self.connection, tx, conn, { let model = with_conn!(&*self.connection, tx, conn, {
proxy_host::Entity::find_by_id(proxy_id) proxy_host::Entity::find_by_id(proxy_id)
@@ -255,6 +260,25 @@ impl ProxyService for ProxyServiceImpl {
Ok(()) Ok(())
}) })
} }
async fn generate_config(
&self,
builder: &mut NginxConfigBuilder,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> {
let proxies = self
.get_proxies(
None,
Some(ProxyHostListOptions {
include_upstream: true,
..Default::default()
}),
tx,
)
.await?;
builder.add_proxy_hosts(proxies);
Ok(())
}
} }
#[cfg(test)] #[cfg(test)]
@@ -331,7 +355,7 @@ mod tests {
locations: Vec::new(), locations: Vec::new(),
}; };
let res = svc.create_proxy(create_info, None).await; let res = svc.create_proxy(create_info, &None).await;
assert!(res.is_ok()); assert!(res.is_ok());
let info = res.expect("Failed to create proxy"); let info = res.expect("Failed to create proxy");
assert_eq!(info.domain, "example.com"); assert_eq!(info.domain, "example.com");
@@ -345,7 +369,7 @@ mod tests {
let svc = ProxyServiceImpl::new(Arc::new(db)); let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc let res = svc
.get_total_proxies(None, None) .get_total_proxies(None, &None)
.await .await
.expect("Failed to get total proxies"); .expect("Failed to get total proxies");
assert_eq!(res, 0u64); assert_eq!(res, 0u64);
@@ -398,7 +422,7 @@ mod tests {
.into_connection(); .into_connection();
let svc = ProxyServiceImpl::new(Arc::new(db)); let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.get_proxies(None, None, None).await; let res = svc.get_proxies(None, None, &None).await;
assert!(res.is_ok()); assert!(res.is_ok());
let list = res.expect("Failed to get proxies"); let list = res.expect("Failed to get proxies");
assert_eq!(list.len(), 2); assert_eq!(list.len(), 2);
@@ -431,7 +455,7 @@ mod tests {
.into_connection(); .into_connection();
let svc = ProxyServiceImpl::new(Arc::new(db)); let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.get_proxy(id, None, None).await; let res = svc.get_proxy(id, None, &None).await;
assert!(res.is_ok()); assert!(res.is_ok());
let got = res.expect("Failed to get proxy"); let got = res.expect("Failed to get proxy");
assert_eq!(got.id, id); assert_eq!(got.id, id);
@@ -444,7 +468,7 @@ mod tests {
.into_connection(); .into_connection();
let svc = ProxyServiceImpl::new(Arc::new(db)); let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.get_proxy(uuid::Uuid::new_v4(), None, None).await; let res = svc.get_proxy(uuid::Uuid::new_v4(), None, &None).await;
assert!(matches!(res, Err(ServiceError::NotFound(_)))); assert!(matches!(res, Err(ServiceError::NotFound(_))));
} }
@@ -510,7 +534,7 @@ mod tests {
default_upstream_id: None, default_upstream_id: None,
}; };
let res = svc.update_proxy(id, update_info, None).await; let res = svc.update_proxy(id, update_info, &None).await;
assert!(res.is_ok()); assert!(res.is_ok());
let got = res.expect("Failed to update proxy"); let got = res.expect("Failed to update proxy");
assert_eq!(got.name.expect("Name should be present"), "new"); assert_eq!(got.name.expect("Name should be present"), "new");
@@ -541,7 +565,7 @@ mod tests {
meta: None, meta: None,
default_upstream_id: None, default_upstream_id: None,
}, },
None, &None,
) )
.await; .await;
@@ -580,7 +604,7 @@ mod tests {
let svc = ProxyServiceImpl::new(Arc::new(db)); let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.delete_proxy(id, None).await; let res = svc.delete_proxy(id, &None).await;
assert!(res.is_ok()); assert!(res.is_ok());
} }
@@ -592,7 +616,7 @@ mod tests {
let svc = ProxyServiceImpl::new(Arc::new(db)); let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.delete_proxy(uuid::Uuid::new_v4(), None).await; let res = svc.delete_proxy(uuid::Uuid::new_v4(), &None).await;
assert!(matches!(res, Err(ServiceError::NotFound(_)))); assert!(matches!(res, Err(ServiceError::NotFound(_))));
} }
} }

View File

@@ -88,7 +88,7 @@ pub trait UpstreamService: Send + Sync {
async fn generate_config( async fn generate_config(
&self, &self,
builder: &mut NginxConfigBuilder, builder: &mut NginxConfigBuilder,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError>; ) -> Result<(), ServiceError>;
} }
@@ -457,7 +457,7 @@ impl UpstreamService for UpstreamServiceImpl {
async fn generate_config( async fn generate_config(
&self, &self,
builder: &mut NginxConfigBuilder, builder: &mut NginxConfigBuilder,
tx: Option<&mut DatabaseTransaction>, tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> { ) -> Result<(), ServiceError> {
// get all upstreams and their targets // get all upstreams and their targets
let upstreams = with_conn!(&*self.connection, tx, conn, { let upstreams = with_conn!(&*self.connection, tx, conn, {