Refactor, add NixStorePath class
This commit is contained in:
		
							
								
								
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -450,7 +450,7 @@ dependencies = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "nixos-exporter" | name = "nixos-exporter" | ||||||
| version = "0.3.0" | version = "0.4.0" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "axum", |  "axum", | ||||||
|  "reqwest", |  "reqwest", | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| [package] | [package] | ||||||
| name = "nixos-exporter" | name = "nixos-exporter" | ||||||
| version = "0.3.0" | version = "0.4.0" | ||||||
| edition = "2021" | edition = "2021" | ||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|     in { |     in { | ||||||
|       nixos-exporter = pkgs.rustPlatform.buildRustPackage rec { |       nixos-exporter = pkgs.rustPlatform.buildRustPackage rec { | ||||||
|         pname = "nixos-exporter"; |         pname = "nixos-exporter"; | ||||||
|         version = "0.3.0"; |         version = "0.4.0"; | ||||||
|  |  | ||||||
|         src = ./.; |         src = ./.; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -9,6 +9,7 @@ use axum::{ | |||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| use std::net::SocketAddr; | use std::net::SocketAddr; | ||||||
| use std::str::FromStr; | use std::str::FromStr; | ||||||
|  | use std::path::PathBuf; | ||||||
|  |  | ||||||
| #[derive(Clone, PartialEq)] | #[derive(Clone, PartialEq)] | ||||||
| enum OperationMode { | enum OperationMode { | ||||||
| @@ -58,16 +59,44 @@ impl AppState{ | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| fn parse_nix_store_path(path: std::path::PathBuf) -> Result<(String, String), String> { | #[derive(Clone)] | ||||||
|     let (hash, name) = path.iter().nth(3) | struct NixStorePath { | ||||||
|  |     hash: String, | ||||||
|  |     name: String, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl NixStorePath { | ||||||
|  |     pub fn from_str_symlink(path: &str) -> Result<Self, String> { | ||||||
|  |         Ok(Self::from_path_buf_symlink(PathBuf::from(path))?) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn from_path_buf_symlink(path: PathBuf) -> Result<Self, String> { | ||||||
|  |         Ok(Self::from_path_buf(path.read_link().map_err(|err| err.to_string())?)?) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn from_path_buf(path: PathBuf) -> Result<Self, String> { | ||||||
|  |         let store_path_name = path.iter().nth(3) | ||||||
|             .ok_or_else(|| String::from("Can't read store path name"))? |             .ok_or_else(|| String::from("Can't read store path name"))? | ||||||
|             .to_str() |             .to_str() | ||||||
|             .ok_or_else(|| String::from("Failed converting store path name to string"))? |             .ok_or_else(|| String::from("Failed converting store path name to string"))? | ||||||
|         .split_once("-") |             .to_string(); | ||||||
|         .ok_or_else(|| String::from("Failed splitting store path name for hash and name"))?; |         Ok(Self::from_store_path_name(store_path_name)?) | ||||||
|     return Ok((hash.to_string(), name.to_string())); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn from_store_path_name(store_path_name: String) -> Result<Self, String> { | ||||||
|  |         let (hash, name) = store_path_name | ||||||
|  |             .split_once("-") | ||||||
|  |             .ok_or_else(|| String::from("Failed splitting store path name for hash and name"))?; | ||||||
|  |         Ok(Self { | ||||||
|  |             hash: hash.to_string(), | ||||||
|  |             name: name.to_string(), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn to_prometheus_metric(self, infix: String) -> Result<String, String> { | ||||||
|  |         return Ok(format!("nixos_{}_hash{{hash=\"{}\"}} 1\nnixos_{}_name{{name=\"{}\"}} 1\n", infix, self.hash, infix, self.name)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| #[tokio::main] | #[tokio::main] | ||||||
| async fn main() { | async fn main() { | ||||||
| @@ -143,30 +172,24 @@ async fn main() { | |||||||
|         .unwrap(); |         .unwrap(); | ||||||
| } | } | ||||||
|  |  | ||||||
| fn parse_symlink(path: String) -> Result<(String, String), String> { |  | ||||||
|     let symlink = std::fs::read_link(path).map_err(|err| err.to_string())?; |  | ||||||
|  |  | ||||||
|     let (hash, name) = parse_nix_store_path(symlink)?; |  | ||||||
|  |  | ||||||
|     Ok((String::from(hash), String::from(name))) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| fn gen_prometheus_metric(path: String, infix: String) -> Result<String, String> { |  | ||||||
|     let (hash, name) = parse_symlink(path).map_err(|err| err)?; |  | ||||||
|  |  | ||||||
|     return Ok(format!("nixos_{}_hash{{hash=\"{}\"}} 1\nnixos_{}_name{{name=\"{}\"}} 1\n", infix, hash, infix, name)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async fn metrics() -> Result<(StatusCode, impl IntoResponse), (StatusCode, impl IntoResponse)> { | async fn metrics() -> Result<(StatusCode, impl IntoResponse), (StatusCode, impl IntoResponse)> { | ||||||
|  |     let nix_store_paths = HashMap::from([ | ||||||
|  |     ("current_system", NixStorePath::from_str_symlink("/run/current-system") | ||||||
|  |         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), | ||||||
|  |     ("current_system_kernel", NixStorePath::from_str_symlink("/run/current-system/kernel") | ||||||
|  |         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), | ||||||
|  |     ("booted_system", NixStorePath::from_str_symlink("/run/booted-system") | ||||||
|  |         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), | ||||||
|  |     ("booted_system_kernel", NixStorePath::from_str_symlink("/run/booted-system/kernel") | ||||||
|  |         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), | ||||||
|  |     ]); | ||||||
|  |  | ||||||
|     let mut out = String::new(); |     let mut out = String::new(); | ||||||
|     out.push_str(&gen_prometheus_metric(String::from("/run/current-system"), String::from("current_system")) |     for (infix, nix_store_path) in nix_store_paths.iter() { | ||||||
|         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); |         out.push_str(nix_store_path.clone().to_prometheus_metric(infix.to_string()) | ||||||
|     out.push_str(&gen_prometheus_metric(String::from("/run/current-system/kernel"), String::from("current_system_kernel")) |             .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?.as_str()); | ||||||
|         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); |     } | ||||||
|     out.push_str(&gen_prometheus_metric(String::from("/run/booted-system"), String::from("booted_system")) |  | ||||||
|         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); |  | ||||||
|     out.push_str(&gen_prometheus_metric(String::from("/run/booted-system/kernel"), String::from("booted_system_kernel")) |  | ||||||
|         .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); |  | ||||||
|     return Ok(( |     return Ok(( | ||||||
|         StatusCode::OK, |         StatusCode::OK, | ||||||
|         out, |         out, | ||||||
| @@ -213,8 +236,9 @@ async fn check(State(app_state): State<AppState>, Query(params): Query<HashMap<S | |||||||
|     let nix_store_path = hydra_body["buildoutputs"]["out"]["path"].as_str() |     let nix_store_path = hydra_body["buildoutputs"]["out"]["path"].as_str() | ||||||
|         .ok_or_else(|| (StatusCode::INTERNAL_SERVER_ERROR, "No buildoutput found in Hydra"))?; |         .ok_or_else(|| (StatusCode::INTERNAL_SERVER_ERROR, "No buildoutput found in Hydra"))?; | ||||||
|  |  | ||||||
|     let (hydra_system_hash, _) = parse_nix_store_path(std::path::PathBuf::from(nix_store_path)) |     let hydra_system_hash = NixStorePath::from_path_buf(std::path::PathBuf::from(nix_store_path)) | ||||||
|         .map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, "Invalid store path returned by Hydra"))?; |         .map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, "Invalid store path returned by Hydra"))? | ||||||
|  |         .hash; | ||||||
|  |  | ||||||
|     let mut status = "0"; |     let mut status = "0"; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user