use std::{collections::BTreeSet, fs, path::PathBuf}; fn repo_root() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() .and_then(|p| p.parent()) .expect("api crate should live under repo root") .to_path_buf() } #[test] fn loki_and_tempo_s3_config_variants_are_syntactically_valid() { let root = repo_root(); for file in [ root.join("observability/loki/config.s3.yml"), root.join("observability/tempo/config.s3.yml"), ] { let raw = fs::read_to_string(&file).unwrap_or_else(|e| panic!("{file:?}: {e}")); let _: serde_yaml::Value = serde_yaml::from_str(&raw).unwrap_or_else(|e| panic!("{file:?}: {e}")); } } #[test] fn grafana_provisioning_files_are_syntactically_valid() { let root = repo_root(); let datasources = fs::read_to_string( root.join("observability/grafana/provisioning/datasources/datasources.yml"), ) .expect("missing grafana datasources provisioning file"); let dashboards = fs::read_to_string( root.join("observability/grafana/provisioning/dashboards/dashboards.yml"), ) .expect("missing grafana dashboards provisioning file"); let _datasources_yaml: serde_yaml::Value = serde_yaml::from_str(&datasources).expect("invalid grafana datasources yaml"); let _dashboards_yaml: serde_yaml::Value = serde_yaml::from_str(&dashboards).expect("invalid grafana dashboards yaml"); } #[test] fn grafana_dashboards_are_syntactically_valid_json() { let root = repo_root(); let dashboards_dir = root.join("observability/grafana/dashboards"); let mut found = 0usize; for entry in fs::read_dir(&dashboards_dir).expect("missing dashboards dir") { let entry = entry.expect("failed to read dashboards dir entry"); let path = entry.path(); if path.extension().and_then(|e| e.to_str()) != Some("json") { continue; } found += 1; let raw = fs::read_to_string(&path).expect("failed to read dashboard json"); let _: serde_json::Value = serde_json::from_str(&raw).unwrap_or_else(|e| panic!("{path:?}: {e}")); } assert!(found > 0, "expected at least one dashboard json file"); } #[test] fn vmagent_config_parses_and_includes_required_jobs() { let root = repo_root(); let scrape = fs::read_to_string(root.join("observability/vmagent/scrape.yml")) .expect("missing vmagent scrape config"); let value: serde_yaml::Value = serde_yaml::from_str(&scrape).expect("invalid vmagent scrape yaml"); let mut job_names = BTreeSet::::new(); if let Some(scrape_configs) = value.get("scrape_configs").and_then(|v| v.as_sequence()) { for cfg in scrape_configs { if let Some(job) = cfg.get("job_name").and_then(|v| v.as_str()) { job_names.insert(job.to_string()); } } } for required in ["victoria-metrics", "vmagent", "control-api"] { assert!( job_names.contains(required), "vmagent scrape config missing required job_name={required}" ); } }