Make options configurable
This commit is contained in:
		
							
								
								
									
										92
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| use axum::{ | ||||
|     extract::Query, | ||||
|     extract::{State, Query}, | ||||
|     http::StatusCode, | ||||
|     response::{IntoResponse, Response}, | ||||
|     routing::get, | ||||
| @@ -10,13 +10,54 @@ use std::collections::HashMap; | ||||
| use std::net::SocketAddr; | ||||
| use std::str::FromStr; | ||||
|  | ||||
| #[derive(PartialEq)] | ||||
| #[derive(Clone, PartialEq)] | ||||
| enum OperationMode { | ||||
|     None, | ||||
|     Exporter, | ||||
|     Validator, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| struct AppState { | ||||
|     listen: String, | ||||
|     operationmode: OperationMode, | ||||
|     prometheus_url: String, | ||||
|     prometheus_query_tag_template: String, | ||||
|     hydra_url: String, | ||||
|     hydra_job_template: String, | ||||
| } | ||||
|  | ||||
| impl AppState{ | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             listen: String::from("[::]:9152"), | ||||
|             operationmode: OperationMode::None, | ||||
|             prometheus_url: String::from(""), | ||||
|             prometheus_query_tag_template: String::from("instance=\"{}\""), | ||||
|             hydra_url: String::from(""), | ||||
|             hydra_job_template: String::from("nixfiles/nixfiles/nixosConfigurations.{}"), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn is_valid(self) -> bool { | ||||
|         let mut valid = true; | ||||
|         if self.operationmode == OperationMode::None { | ||||
|             println!("operationmode is not set"); | ||||
|             valid = false; | ||||
|         } | ||||
|         if self.prometheus_url == String::from("") { | ||||
|             println!("Prometheus url is not specified"); | ||||
|             valid = false; | ||||
|         } | ||||
|         if self.hydra_url == String::from("") { | ||||
|             println!("Hydra url is not specified"); | ||||
|             valid = false; | ||||
|         } | ||||
|  | ||||
|         return valid; | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn parse_nix_store_path(path: std::path::PathBuf) -> Result<(String, String), String> { | ||||
|     let (hash, name) = path.file_name() | ||||
|         .ok_or_else(String::default)? | ||||
| @@ -27,10 +68,11 @@ fn parse_nix_store_path(path: std::path::PathBuf) -> Result<(String, String), St | ||||
|     return Ok((hash.to_string(), name.to_string())); | ||||
| } | ||||
|  | ||||
|  | ||||
| #[tokio::main] | ||||
| async fn main() { | ||||
|     let mut listen = String::from("[::]:9152"); | ||||
|     let mut operationmode = OperationMode::None; | ||||
|     let mut app_state = AppState::new(); | ||||
|  | ||||
|     let mut args = std::env::args(); | ||||
|     let name = args.next().unwrap(); | ||||
|     loop { | ||||
| @@ -48,13 +90,25 @@ async fn main() { | ||||
|                 std::process::exit(0); | ||||
|             } | ||||
|             "--listen" => { | ||||
|                 listen = args.next().unwrap(); | ||||
|                 app_state.listen = args.next().unwrap(); | ||||
|             } | ||||
|             "--prometheus-url" => { | ||||
|                 app_state.prometheus_url = args.next().unwrap(); | ||||
|             } | ||||
|             "--prometheus-query-tag-template" => { | ||||
|                 app_state.prometheus_query_tag_template = args.next().unwrap(); | ||||
|             } | ||||
|             "--hydra-url" => { | ||||
|                 app_state.hydra_url = args.next().unwrap(); | ||||
|             } | ||||
|             "--hydra-job-template" => { | ||||
|                 app_state.hydra_job_template = args.next().unwrap(); | ||||
|             } | ||||
|             "exporter" => { | ||||
|                 operationmode = OperationMode::Exporter; | ||||
|                 app_state.operationmode = OperationMode::Exporter; | ||||
|             } | ||||
|             "validator" => { | ||||
|                 operationmode = OperationMode::Validator; | ||||
|                 app_state.operationmode = OperationMode::Validator; | ||||
|             } | ||||
|             unknown => { | ||||
|                 println!("unknown option: {}", unknown); | ||||
| @@ -63,11 +117,15 @@ async fn main() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if !app_state.clone().is_valid() { | ||||
|         std::process::exit(1); | ||||
|     } | ||||
|  | ||||
|     let mut app = Router::new(); | ||||
|     if operationmode == OperationMode::Exporter { | ||||
|     if app_state.operationmode == OperationMode::Exporter { | ||||
|         println!("Running NixOS Exporter in Exporter mode"); | ||||
|         app = app.route("/metrics", get(metrics)); | ||||
|     } else if operationmode == OperationMode::Validator { | ||||
|     } else if app_state.operationmode == OperationMode::Validator { | ||||
|         println!("Running NixOS Exporter in Validator mode"); | ||||
|         app = app.route("/metrics", get(check)); | ||||
|     } else { | ||||
| @@ -75,7 +133,9 @@ async fn main() { | ||||
|         std::process::exit(1); | ||||
|     }; | ||||
|  | ||||
|     let addr = SocketAddr::from_str(&listen).unwrap(); | ||||
|     let app = app.with_state(app_state.clone()); | ||||
|  | ||||
|     let addr = SocketAddr::from_str(&app_state.listen.clone()).unwrap(); | ||||
|     println!("listening on http://{}", addr); | ||||
|     axum::Server::bind(&addr) | ||||
|         .serve(app.into_make_service()) | ||||
| @@ -110,7 +170,7 @@ async fn metrics() -> Response { | ||||
|     ).into_response() | ||||
| } | ||||
|  | ||||
| async fn check(Query(params): Query<HashMap<String, String>>) -> Response { | ||||
| async fn check(State(app_state): State<AppState>, Query(params): Query<HashMap<String, String>>) -> Response { | ||||
|     let target = match params.get("target") { | ||||
|         Some(target) => target, | ||||
|         None => { | ||||
| @@ -118,9 +178,13 @@ async fn check(Query(params): Query<HashMap<String, String>>) -> Response { | ||||
|         }, | ||||
|     }; | ||||
|  | ||||
|     if target.contains("\"") { | ||||
|         return (StatusCode::INTERNAL_SERVER_ERROR, "Invalid target name").into_response(); | ||||
|     } | ||||
|  | ||||
|     let client = reqwest::Client::new(); | ||||
|  | ||||
|     let prometheus_req = match client.get(format!("https://prometheus.monitoring.clerie.de/api/v1/query?query=nixos_nixos_current_system_hash{{job=%22nixos-exporter%22,instance=%22{}.mon.clerie.de:9152%22}}", target)) | ||||
|     let prometheus_req = match client.get(format!("{}/api/v1/query?query=nixos_nixos_current_system_hash{{{}}}", app_state.prometheus_url, app_state.prometheus_query_tag_template.clone().replace("{}", target))) | ||||
|         .header("Accept", "application/json") | ||||
|         .send().await { | ||||
|             Ok(req) => req, | ||||
| @@ -151,7 +215,7 @@ async fn check(Query(params): Query<HashMap<String, String>>) -> Response { | ||||
|         }, | ||||
|     }; | ||||
|  | ||||
|     let hydra_req = match client.get(format!("https://hydra.clerie.de/job/nixfiles/nixfiles/nixosConfigurations.{}/latest", target)) | ||||
|     let hydra_req = match client.get(format!("{}/job/{}/latest", app_state.hydra_url, app_state.hydra_job_template.clone().replace("{}", target))) | ||||
|         .header("Accept", "application/json") | ||||
|         .send().await { | ||||
|             Ok(req) => req, | ||||
| @@ -196,6 +260,6 @@ async fn check(Query(params): Query<HashMap<String, String>>) -> Response { | ||||
|  | ||||
|     return ( | ||||
|         StatusCode::OK, | ||||
|         format!("nixos_current_system_valid{{target=\"{}.net.clerie.de:9152\"}} {}\n", target, status) | ||||
|         format!("nixos_current_system_valid{{{}}} {}\n", app_state.prometheus_query_tag_template.clone().replace("{}", target), status) | ||||
|     ).into_response(); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user