Async apply of config via API

This commit is contained in:
Ara Sadoyan
2026-01-20 19:16:27 +01:00
parent 6c1d3c5ef8
commit baebe1c00f
3 changed files with 29 additions and 26 deletions

View File

@@ -40,7 +40,6 @@ pub async fn load_configuration(d: &str, kind: &str) -> (Option<Configuration>,
return (None, e.to_string());
}
};
let mut toreturn = Configuration::default();
populate_headers_and_auth(&mut toreturn, &parsed).await;
@@ -69,7 +68,6 @@ pub async fn load_configuration(d: &str, kind: &str) -> (Option<Configuration>,
async fn populate_headers_and_auth(config: &mut Configuration, parsed: &Config) {
let mut ch: Vec<(Arc<str>, Arc<str>)> = Vec::new();
ch.push((Arc::from("Server"), Arc::from("Aralez")));
// println!("{:?}", &parsed.client_headers);
if let Some(headers) = &parsed.client_headers {
for header in headers {
if let Some((key, val)) = header.split_once(':') {

View File

@@ -12,14 +12,16 @@ pub struct GetHostsReturHeaders {
#[async_trait]
pub trait GetHost {
// fn get_host<'a>(&self, peer: &str, path: &str, backend_id: Option<&str>) -> Option<&'a InnerMap>;
fn get_host(&self, peer: &str, path: &str, backend_id: Option<&str>) -> Option<Arc<InnerMap>>;
fn get_header(&self, peer: &str, path: &str) -> Option<GetHostsReturHeaders>;
// fn get_upstreams(&self) -> Arc<UpstreamsDashMap>;
}
#[async_trait]
impl GetHost for LB {
// fn get_upstreams(&self) -> Arc<UpstreamsDashMap> {
// self.ump_full.clone()
// }
fn get_host(&self, peer: &str, path: &str, backend_id: Option<&str>) -> Option<Arc<InnerMap>> {
if let Some(b) = backend_id {
if let Some(bb) = self.ump_byid.get(b) {

View File

@@ -1,5 +1,5 @@
use crate::utils::discovery::APIUpstreamProvider;
use crate::utils::structs::Configuration;
use crate::utils::structs::{Config, Configuration};
use axum::body::Body;
use axum::extract::{Query, State};
use axum::http::{Response, StatusCode};
@@ -82,37 +82,41 @@ pub async fn run_server(config: &APIUpstreamProvider, mut to_return: Sender<Conf
axum::serve(listener, app).await.unwrap();
}
async fn conf(State(mut st): State<AppState>, Query(params): Query<HashMap<String, String>>, content: String) -> impl IntoResponse {
async fn conf(State(st): State<AppState>, Query(params): Query<HashMap<String, String>>, content: String) -> impl IntoResponse {
if !st.config_api_enabled {
return Response::builder()
.status(StatusCode::FORBIDDEN)
.body(Body::from("Config remote API is disabled !\n"))
.unwrap();
return Response::builder().status(StatusCode::FORBIDDEN).body(Body::from("Config API is disabled !\n")).unwrap();
}
if let Some(s) = params.get("key") {
if s.to_owned() == st.master_key {
let sl = crate::utils::parceyaml::load_configuration(content.as_str(), "content").await;
if let Some(serverlist) = sl.0 {
let r = st.config_sender.send(serverlist).await;
match r {
Ok(_) => {
return Response::builder().status(StatusCode::OK).body(Body::from("Config, conf file, updated!\n")).unwrap();
}
Err(e) => {
let error_msg = format!("Failed to send configuration: {}\n", e);
return Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body(Body::from(error_msg)).unwrap();
let strcontent = content.as_str();
let parsed = serde_yaml::from_str::<Config>(strcontent);
match parsed {
Ok(_) => {
if let Some(s) = params.get("key") {
if s.to_owned() == st.master_key {
let _ = tokio::spawn(async move { apply_config(content.as_str(), st).await });
return Response::builder().status(StatusCode::OK).body(Body::from("Accepted! Applying in background\n")).unwrap();
}
}
return Response::builder().status(StatusCode::FORBIDDEN).body(Body::from("Access Denied !\n")).unwrap();
}
} else {
let err: String = "Error parsing config file: ".to_owned() + sl.1.as_str() + "\n";
return Response::builder().status(StatusCode::BAD_GATEWAY).body(Body::from(err)).unwrap();
};
Err(err) => {
error!("Failed to parse upstreams file: {}", err);
return Response::builder().status(StatusCode::BAD_GATEWAY).body(Body::from(format!("Failed: {}\n", err))).unwrap();
}
}
}
}
Response::builder().status(StatusCode::FORBIDDEN).body(Body::from("Access Denied !\n")).unwrap()
}
async fn apply_config(content: &str, mut st: AppState) {
let sl = crate::utils::parceyaml::load_configuration(content, "content").await;
if let Some(serverlist) = sl.0 {
let _ = st.config_sender.send(serverlist).await;
}
}
async fn jwt_gen(State(state): State<AppState>, Json(payload): Json<InputKey>) -> (StatusCode, Json<OutToken>) {
if payload.master_key == state.master_key {
let now = SystemTime::now() + Duration::from_secs(payload.valid * 60);
@@ -142,7 +146,6 @@ async fn jwt_gen(State(state): State<AppState>, Json(payload): Json<InputKey>) -
async fn metrics() -> impl IntoResponse {
let metric_families = gather();
let encoder = TextEncoder::new();
let mut buffer = Vec::new();
if let Err(e) = encoder.encode(&metric_families, &mut buffer) {
// encoding error fallback