use crate::metrics::CloudInfo;
use std::time::Duration;
use ureq::config::Config as UreqConfig;
mod alicloud;
mod aws;
mod azure;
mod gcp;
mod hetzner;
mod ovh;
mod upcloud;
const IMDS_TIMEOUT: Duration = Duration::from_secs(1);
fn new_imds_agent() -> ureq::Agent {
UreqConfig::builder()
.timeout_global(Some(IMDS_TIMEOUT))
.build()
.new_agent()
}
fn imds_get(agent: &ureq::Agent, url: &str) -> Option<String> {
imds_get_headers(agent, url, &[])
}
fn imds_get_headers(agent: &ureq::Agent, url: &str, headers: &[(&str, &str)]) -> Option<String> {
let mut req = agent.get(url);
for (k, v) in headers {
req = req.header(*k, *v);
}
req.call()
.ok()
.and_then(|mut r| r.body_mut().read_to_string().ok())
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
}
const PROBES: &[fn() -> Option<CloudInfo>] = &[
aws::probe,
gcp::probe,
azure::probe,
hetzner::probe,
upcloud::probe,
alicloud::probe,
ovh::probe,
];
fn probe_cloud() -> CloudInfo {
let handles: Vec<_> = PROBES.iter().map(|&p| std::thread::spawn(p)).collect();
for handle in handles {
if let Ok(Some(info)) = handle.join() {
return info;
}
}
CloudInfo::default()
}
pub fn spawn_cloud_discovery() -> std::thread::JoinHandle<CloudInfo> {
std::thread::spawn(probe_cloud)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_spawn_cloud_discovery_joins_without_panic() {
let handle = spawn_cloud_discovery();
let _cloud = handle.join().expect("cloud discovery thread panicked");
}
}