diff --git a/Cargo.lock b/Cargo.lock index 66e13a0..b770286 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -450,7 +450,7 @@ dependencies = [ [[package]] name = "nixos-exporter" -version = "0.1.0" +version = "0.2.0" dependencies = [ "axum", "reqwest", diff --git a/Cargo.toml b/Cargo.toml index 1c86dda..698feba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nixos-exporter" -version = "0.1.0" +version = "0.2.0" edition = "2021" [dependencies] diff --git a/src/main.rs b/src/main.rs index 3f1a250..d783420 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use axum::{ extract::{State, Query}, http::StatusCode, - response::{IntoResponse, Response}, + response::IntoResponse, routing::get, Router, }; @@ -144,113 +144,64 @@ async fn main() { } fn get_current_system() -> Result<(String, String), String> { - let symlink = match std::fs::read_link("/run/current-system") { - Ok(symlink) => symlink, - Err(err) => return Err(err.to_string()), - }; + let symlink = std::fs::read_link("/run/current-system").map_err(|err| err.to_string())?; let (hash, name) = parse_nix_store_path(symlink)?; Ok((String::from(hash), String::from(name))) } -async fn metrics() -> Response { - let current_system = get_current_system(); - let (hash, name) = match current_system { - Ok((hash, name)) => (hash, name), - Err(err) => { - println!("failed: {}", err); - return (StatusCode::INTERNAL_SERVER_ERROR, "").into_response(); - } - }; +async fn metrics() -> Result<(StatusCode, impl IntoResponse), (StatusCode, impl IntoResponse)> { + let (hash, name) = get_current_system().map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, ""))?; - ( + return Ok(( StatusCode::OK, format!("nixos_current_system_hash{{hash=\"{}\"}} 1\nnixos_current_system_name{{name=\"{}\"}} 1\n", hash, name) - ).into_response() + )); } -async fn check(State(app_state): State, Query(params): Query>) -> Response { - let target = match params.get("target") { - Some(target) => target, - None => { - return (StatusCode::NOT_FOUND, "specify target").into_response(); - }, - }; +async fn check(State(app_state): State, Query(params): Query>) -> Result<(StatusCode, impl IntoResponse), (StatusCode, impl IntoResponse)> { + let target = params.get("target") + .ok_or_else(|| (StatusCode::NOT_FOUND, "specify target"))?; if target.contains("\"") { - return (StatusCode::INTERNAL_SERVER_ERROR, "Invalid target name").into_response(); + return Err((StatusCode::INTERNAL_SERVER_ERROR, "Invalid target name")); } let client = reqwest::Client::new(); - let prometheus_req = match client.get(format!("{}/api/v1/query?query=nixos_current_system_hash{{{}}}", app_state.prometheus_url, app_state.prometheus_query_tag_template.clone().replace("{}", target))) + let prometheus_req = client.get(format!("{}/api/v1/query?query=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, - Err(_) => { - return (StatusCode::INTERNAL_SERVER_ERROR, "Promehteus can't get reached").into_response(); - }, - }; + .send().await + .map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, "Promehteus can't get reached"))?; - - match prometheus_req.status() { - reqwest::StatusCode::OK => (), - _ => { - return (StatusCode::NOT_FOUND, "Target does not exist in Hydra").into_response(); - }, + if prometheus_req.status() != reqwest::StatusCode::OK { + return Err((StatusCode::NOT_FOUND, "Target does not exist in Hydra")); } - let prometheus_body = match prometheus_req.json::().await { - Ok(body) => body, - Err(_) => { - return (StatusCode::INTERNAL_SERVER_ERROR, "Invalid response from Hydra").into_response(); - }, - }; + let prometheus_body = prometheus_req.json::().await + .map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, "Invalid response from Hydra"))?; - let current_system_hash = match prometheus_body["data"]["result"][0]["metric"]["hash"].as_str() { - Some(nix_store_path) => nix_store_path, - _ => { - return (StatusCode::INTERNAL_SERVER_ERROR, "No buildoutput found in Hydra").into_response(); - }, - }; + let current_system_hash = prometheus_body["data"]["result"][0]["metric"]["hash"].as_str() + .ok_or_else(|| (StatusCode::INTERNAL_SERVER_ERROR, "No buildoutput found in Hydra"))?; - let hydra_req = match client.get(format!("{}/job/{}/latest", app_state.hydra_url, app_state.hydra_job_template.clone().replace("{}", target))) + let hydra_req = 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, - Err(_) => { - return (StatusCode::INTERNAL_SERVER_ERROR, "Hydra can't get reached").into_response(); - }, - }; + .send().await + .map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, "Hydra can't get reached"))?; - match hydra_req.status() { - reqwest::StatusCode::OK => (), - _ => { - return (StatusCode::NOT_FOUND, "Target does not exist in Hydra").into_response(); - }, + if hydra_req.status() != reqwest::StatusCode::OK { + return Err((StatusCode::NOT_FOUND, "Target does not exist in Hydra")); } - let hydra_body = match hydra_req.json::().await { - Ok(body) => body, - Err(_) => { - return (StatusCode::INTERNAL_SERVER_ERROR, "Invalid response from Hydra").into_response(); - }, - }; + let hydra_body = hydra_req.json::().await + .map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, "Invalid response from Hydra"))?; - let nix_store_path = match hydra_body["buildoutputs"]["out"]["path"].as_str() { - Some(nix_store_path) => nix_store_path, - _ => { - return (StatusCode::INTERNAL_SERVER_ERROR, "No buildoutput found in Hydra").into_response(); - }, - }; + let nix_store_path = hydra_body["buildoutputs"]["out"]["path"].as_str() + .ok_or_else(|| (StatusCode::INTERNAL_SERVER_ERROR, "No buildoutput found in Hydra"))?; - let (hydra_system_hash, _) = match parse_nix_store_path(std::path::PathBuf::from(nix_store_path)) { - Ok((hash, name)) => (hash, name), - Err(_) => { - return (StatusCode::INTERNAL_SERVER_ERROR, "Invalid store path returned by Hydra").into_response(); - }, - }; + let (hydra_system_hash, _) = parse_nix_store_path(std::path::PathBuf::from(nix_store_path)) + .map_err(|_err| (StatusCode::INTERNAL_SERVER_ERROR, "Invalid store path returned by Hydra"))?; let mut status = "0"; @@ -258,8 +209,8 @@ async fn check(State(app_state): State, Query(params): Query