use std::collections::HashMap;
use std::sync::{LazyLock, Mutex, RwLock};
use std::thread::{self, JoinHandle};
use std::time::Duration;
use regex::Regex;
use serde_json::Value;
const PROBE_TIMEOUT: Duration = Duration::from_millis(250);
const DMI_FIELDS: &[&str] = &[
"sys_vendor",
"board_vendor",
"product_name",
"chassis_asset_tag",
"bios_vendor",
"product_serial",
];
const DMI_RULES: &[(&str, &str, &str, &str)] = &[
("chassis_asset_tag", "oraclecloud.com", "eq", "oci"),
("chassis_asset_tag", "7783-7084-3265-9085-8269-3286-77", "eq", "azure"),
("product_name", "google compute engine", "eq", "gcp"),
("product_name", "alibaba cloud ecs", "eq", "alibaba"),
("sys_vendor", "amazon ec2", "eq", "aws"),
("sys_vendor", "digitalocean", "eq", "digitalocean"),
("sys_vendor", "hetzner", "eq", "hetzner"),
("sys_vendor", "vultr", "eq", "vultr"),
("sys_vendor", "scaleway", "eq", "scaleway"),
("sys_vendor", "microsoft corporation", "eq", "azure"),
("sys_vendor", "amazon", "contains", "aws"),
("sys_vendor", "google", "contains", "gcp"),
("sys_vendor", "alibaba cloud", "contains", "alibaba"),
("sys_vendor", "ovh", "contains", "ovh"),
];
pub(crate) const FANOUT_PROBES: &[&str] = &["aws", "gcp", "azure"];
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CloudEnv {
pub provider: Option<String>,
pub region: Option<String>,
pub source: &'static str,
pub instance_type: Option<String>,
}
impl CloudEnv {
pub fn none() -> Self {
Self {
provider: None,
region: None,
source: "none",
instance_type: None,
}
}
}
static RESULT: LazyLock<RwLock<CloudEnv>> = LazyLock::new(|| RwLock::new(CloudEnv::none()));
static BG_THREAD: LazyLock<Mutex<Option<JoinHandle<()>>>> = LazyLock::new(|| Mutex::new(None));
type DmiOverride = Box<dyn Fn() -> HashMap<String, String> + Send + Sync>;
static DMI_OVERRIDE: LazyLock<Mutex<Option<DmiOverride>>> = LazyLock::new(|| Mutex::new(None));
type ProbeFn = Box<dyn Fn() -> Option<CloudEnv> + Send + Sync>;
static PROBE_OVERRIDES: LazyLock<Mutex<HashMap<String, ProbeFn>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
pub fn get_cloud_env() -> CloudEnv {
match RESULT.read() {
Ok(g) => g.clone(),
Err(poisoned) => poisoned.into_inner().clone(),
}
}
fn set_result(env: CloudEnv) {
let mut guard = match RESULT.write() {
Ok(g) => g,
Err(poisoned) => poisoned.into_inner(),
};
*guard = env;
}
static AZ_CA_REGION_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"(?i)\.([a-z0-9-]+)\.azurecontainerapps\.io$")
.expect("static Azure CA regex compiles")
});
fn azure_container_apps_region() -> Option<String> {
for var in ["CONTAINER_APP_HOSTNAME", "CONTAINER_APP_ENV_DNS_SUFFIX"] {
if let Ok(value) = std::env::var(var) {
if let Some(caps) = AZ_CA_REGION_RE.captures(&value) {
if let Some(m) = caps.get(1) {
return Some(m.as_str().to_lowercase());
}
}
}
}
None
}
fn env_nonempty(name: &str) -> Option<String> {
match std::env::var(name) {
Ok(v) if !v.is_empty() => Some(v),
_ => None,
}
}
fn detect_env() -> Option<CloudEnv> {
if env_nonempty("MODAL_TASK_ID").is_some() || env_nonempty("MODAL_IMAGE_ID").is_some() {
return Some(CloudEnv {
provider: Some("modal".into()),
region: env_nonempty("MODAL_REGION"),
source: "env",
instance_type: None,
});
}
if env_nonempty("RUNPOD_POD_ID").is_some() || env_nonempty("RUNPOD_POD_HOSTNAME").is_some() {
return Some(CloudEnv {
provider: Some("runpod".into()),
region: env_nonempty("RUNPOD_DC_ID"),
source: "env",
instance_type: None,
});
}
if env_nonempty("RENDER").is_some() || env_nonempty("RENDER_SERVICE_ID").is_some() {
return Some(CloudEnv {
provider: Some("render".into()),
region: None,
source: "env",
instance_type: None,
});
}
if env_nonempty("RAILWAY_PROJECT_ID").is_some()
|| env_nonempty("RAILWAY_ENVIRONMENT_ID").is_some()
{
return Some(CloudEnv {
provider: Some("railway".into()),
region: env_nonempty("RAILWAY_REPLICA_REGION"),
source: "env",
instance_type: None,
});
}
if env_nonempty("DYNO").is_some() {
return Some(CloudEnv {
provider: Some("heroku".into()),
region: None,
source: "env",
instance_type: None,
});
}
if env_nonempty("KOYEB_SERVICE_NAME").is_some() || env_nonempty("KOYEB_APP_NAME").is_some() {
return Some(CloudEnv {
provider: Some("koyeb".into()),
region: env_nonempty("KOYEB_REGION"),
source: "env",
instance_type: None,
});
}
if env_nonempty("FLY_REGION").is_some() || env_nonempty("FLY_APP_NAME").is_some() {
return Some(CloudEnv {
provider: Some("fly".into()),
region: env_nonempty("FLY_REGION"),
source: "env",
instance_type: None,
});
}
if env_nonempty("VERCEL").is_some() || env_nonempty("VERCEL_REGION").is_some() {
return Some(CloudEnv {
provider: Some("vercel".into()),
region: env_nonempty("VERCEL_REGION"),
source: "env",
instance_type: None,
});
}
if env_nonempty("AWS_LAMBDA_FUNCTION_NAME").is_some()
|| env_nonempty("AWS_EXECUTION_ENV").is_some()
|| env_nonempty("ECS_CONTAINER_METADATA_URI_V4").is_some()
|| env_nonempty("ECS_CONTAINER_METADATA_URI").is_some()
|| env_nonempty("AWS_REGION").is_some()
|| env_nonempty("AWS_DEFAULT_REGION").is_some()
{
let region = env_nonempty("AWS_REGION").or_else(|| env_nonempty("AWS_DEFAULT_REGION"));
return Some(CloudEnv {
provider: Some("aws".into()),
region,
source: "env",
instance_type: None,
});
}
if env_nonempty("WEBSITE_SITE_NAME").is_some()
|| env_nonempty("FUNCTIONS_WORKER_RUNTIME").is_some()
|| env_nonempty("CONTAINER_APP_NAME").is_some()
{
let region = env_nonempty("REGION_NAME").or_else(azure_container_apps_region);
return Some(CloudEnv {
provider: Some("azure".into()),
region,
source: "env",
instance_type: None,
});
}
if env_nonempty("K_SERVICE").is_some()
|| env_nonempty("K_CONFIGURATION").is_some()
|| env_nonempty("GAE_ENV").is_some()
|| env_nonempty("FUNCTION_TARGET").is_some()
|| env_nonempty("FUNCTION_NAME").is_some()
{
return Some(CloudEnv {
provider: Some("gcp".into()),
region: None,
source: "env",
instance_type: None,
});
}
None
}
fn read_dmi_real() -> HashMap<String, String> {
let mut result = HashMap::new();
for &field in DMI_FIELDS {
if let Ok(raw) = std::fs::read_to_string(format!("/sys/class/dmi/id/{}", field)) {
result.insert(field.to_string(), raw.trim().to_lowercase());
}
}
result
}
fn read_dmi() -> HashMap<String, String> {
if let Some(f) = DMI_OVERRIDE.lock().unwrap().as_ref() {
return f();
}
read_dmi_real()
}
fn detect_dmi() -> Option<CloudEnv> {
let dmi = read_dmi();
for &(field, needle, mode, provider) in DMI_RULES {
let value = match dmi.get(field) {
Some(v) if !v.is_empty() => v.as_str(),
_ => continue,
};
let hit = match mode {
"eq" => value == needle,
"contains" => value.contains(needle),
_ => false,
};
if hit {
return Some(CloudEnv {
provider: Some(provider.to_string()),
region: None,
source: "dmi",
instance_type: None,
});
}
}
None
}
fn http_client() -> Option<reqwest::blocking::Client> {
reqwest::blocking::Client::builder()
.timeout(PROBE_TIMEOUT)
.build()
.ok()
}
pub(crate) fn gcp_path_to_region(value: &str, drop_zone_letter: bool) -> Option<String> {
if value.is_empty() {
return None;
}
let last = value.rsplit('/').next().unwrap_or("");
if last.is_empty() {
return None;
}
if drop_zone_letter {
if !last.contains('-') {
return None;
}
let (region, _zone_letter) = last.rsplit_once('-')?;
return Some(region.to_string());
}
Some(last.to_string())
}
fn probe_aws() -> Option<CloudEnv> {
let client = http_client()?;
let token = client
.put("http://169.254.169.254/latest/api/token")
.header("X-aws-ec2-metadata-token-ttl-seconds", "21600")
.send()
.ok()?
.text()
.ok()?;
let region = client
.get("http://169.254.169.254/latest/meta-data/placement/region")
.header("X-aws-ec2-metadata-token", token.clone())
.send()
.ok()?
.text()
.ok()?
.trim()
.to_string();
let instance_type = client
.get("http://169.254.169.254/latest/meta-data/instance-type")
.header("X-aws-ec2-metadata-token", token)
.send()
.ok()
.and_then(|r| r.text().ok())
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty());
Some(CloudEnv {
provider: Some("aws".into()),
region: if region.is_empty() { None } else { Some(region) },
source: "imds",
instance_type,
})
}
fn probe_gcp() -> Option<CloudEnv> {
let client = http_client()?;
let mut region: Option<String> = None;
if let Ok(resp) = client
.get("http://metadata.google.internal/computeMetadata/v1/instance/region")
.header("Metadata-Flavor", "Google")
.send()
{
if let Ok(body) = resp.text() {
region = gcp_path_to_region(body.trim(), false);
}
}
if region.is_none() {
let body = client
.get("http://metadata.google.internal/computeMetadata/v1/instance/zone")
.header("Metadata-Flavor", "Google")
.send()
.ok()?
.text()
.ok()?;
region = gcp_path_to_region(body.trim(), true);
}
let instance_type = client
.get("http://metadata.google.internal/computeMetadata/v1/instance/machine-type")
.header("Metadata-Flavor", "Google")
.send()
.ok()
.and_then(|r| r.text().ok())
.and_then(|s| {
let trimmed = s.trim();
if trimmed.is_empty() {
None
} else {
trimmed.rsplit('/').next().map(|x| x.to_string())
}
})
.filter(|s| !s.is_empty());
Some(CloudEnv {
provider: Some("gcp".into()),
region,
source: "imds",
instance_type,
})
}
fn probe_azure() -> Option<CloudEnv> {
let client = http_client()?;
let body = client
.get("http://169.254.169.254/metadata/instance?api-version=2021-02-01")
.header("Metadata", "true")
.send()
.ok()?
.text()
.ok()?;
let payload: Value = serde_json::from_str(&body).ok()?;
let compute = payload.get("compute");
let region = compute
.and_then(|c| c.get("location"))
.and_then(|l| l.as_str())
.map(|s| s.to_string())
.filter(|s| !s.is_empty());
let instance_type = compute
.and_then(|c| c.get("vmSize"))
.and_then(|v| v.as_str())
.map(|s| s.to_string())
.filter(|s| !s.is_empty());
Some(CloudEnv {
provider: Some("azure".into()),
region,
source: "imds",
instance_type,
})
}
fn probe_oci() -> Option<CloudEnv> {
let client = http_client()?;
let region = client
.get("http://169.254.169.254/opc/v2/instance/canonicalRegionName")
.header("Authorization", "Bearer Oracle")
.send()
.ok()?
.text()
.ok()?
.trim()
.to_lowercase();
Some(CloudEnv {
provider: Some("oci".into()),
region: if region.is_empty() { None } else { Some(region) },
source: "imds",
instance_type: None,
})
}
fn probe_digitalocean() -> Option<CloudEnv> {
let client = http_client()?;
let region = client
.get("http://169.254.169.254/metadata/v1/region")
.send()
.ok()?
.text()
.ok()?
.trim()
.to_lowercase();
Some(CloudEnv {
provider: Some("digitalocean".into()),
region: if region.is_empty() { None } else { Some(region) },
source: "imds",
instance_type: None,
})
}
fn probe_alibaba() -> Option<CloudEnv> {
let client = http_client()?;
let region = client
.get("http://100.100.100.200/latest/meta-data/region-id")
.send()
.ok()?
.text()
.ok()?
.trim()
.to_lowercase();
Some(CloudEnv {
provider: Some("alibaba".into()),
region: if region.is_empty() { None } else { Some(region) },
source: "imds",
instance_type: None,
})
}
fn dispatch_probe(name: &str) -> Option<CloudEnv> {
if let Some(f) = PROBE_OVERRIDES.lock().unwrap().get(name) {
return f();
}
match name {
"aws" => probe_aws(),
"gcp" => probe_gcp(),
"azure" => probe_azure(),
"oci" => probe_oci(),
"digitalocean" => probe_digitalocean(),
"alibaba" => probe_alibaba(),
_ => None,
}
}
pub(crate) fn run_probe(provider_hint: Option<&str>) -> CloudEnv {
if let Some(hint) = provider_hint {
if matches!(
hint,
"aws" | "gcp" | "azure" | "oci" | "digitalocean" | "alibaba"
) {
if let Some(env) = dispatch_probe(hint) {
return env;
}
return CloudEnv {
provider: Some(hint.to_string()),
region: None,
source: "imds",
instance_type: None,
};
}
}
let (tx, rx) = std::sync::mpsc::channel::<CloudEnv>();
let mut handles = Vec::with_capacity(FANOUT_PROBES.len());
for &name in FANOUT_PROBES {
let tx = tx.clone();
let name_owned = name.to_string();
handles.push(thread::spawn(move || {
if let Some(env) = dispatch_probe(&name_owned) {
let _ = tx.send(env);
}
}));
}
drop(tx);
if let Ok(env) = rx.recv_timeout(PROBE_TIMEOUT + Duration::from_millis(50)) {
return env;
}
CloudEnv::none()
}
pub fn detect_now() -> CloudEnv {
let env = detect_env();
if let Some(ref e) = env {
if e.provider.is_some() && e.region.is_some() {
return e.clone();
}
}
let env_dmi = detect_dmi();
match (env, env_dmi) {
(Some(e), _) => e,
(None, Some(d)) => d,
(None, None) => CloudEnv::none(),
}
}
pub fn start_background_detection(track_network: bool) {
if !track_network {
set_result(CloudEnv::none());
return;
}
let initial = detect_now();
set_result(initial.clone());
if initial.provider.is_some() && initial.region.is_some() {
return;
}
{
let guard = match BG_THREAD.lock() {
Ok(g) => g,
Err(poisoned) => poisoned.into_inner(),
};
if let Some(h) = guard.as_ref() {
if !h.is_finished() {
return;
}
}
}
let hint = initial.provider.clone();
let initial_region = initial.region.clone();
let initial_instance_type = initial.instance_type.clone();
let handle = thread::Builder::new()
.name("dexcost-cloud-detect".to_string())
.spawn(move || {
let env = run_probe(hint.as_deref());
if env.provider.is_some() {
let region = if env.region.is_some() {
env.region
} else {
initial_region
};
let instance_type = if env.instance_type.is_some() {
env.instance_type
} else {
initial_instance_type
};
let final_env = CloudEnv {
provider: env.provider,
region,
source: env.source,
instance_type,
};
set_result(final_env);
}
})
.ok();
if let Some(h) = handle {
let mut guard = match BG_THREAD.lock() {
Ok(g) => g,
Err(poisoned) => poisoned.into_inner(),
};
*guard = Some(h);
}
}
#[doc(hidden)]
pub fn reset_module_for_tests() {
set_result(CloudEnv::none());
*BG_THREAD.lock().unwrap() = None;
}
#[doc(hidden)]
pub fn set_dmi_override_for_tests<F>(f: F)
where
F: Fn() -> HashMap<String, String> + Send + Sync + 'static,
{
*DMI_OVERRIDE.lock().unwrap() = Some(Box::new(f));
}
#[doc(hidden)]
pub fn clear_dmi_override_for_tests() {
*DMI_OVERRIDE.lock().unwrap() = None;
}
#[doc(hidden)]
pub fn set_probe_override_for_tests<F>(name: &str, f: F)
where
F: Fn() -> Option<CloudEnv> + Send + Sync + 'static,
{
PROBE_OVERRIDES
.lock()
.unwrap()
.insert(name.to_string(), Box::new(f));
}
#[doc(hidden)]
pub fn clear_probe_overrides_for_tests() {
PROBE_OVERRIDES.lock().unwrap().clear();
}
#[doc(hidden)]
pub fn set_result_for_tests(env: CloudEnv) {
set_result(env);
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Mutex as StdMutex;
use std::time::Instant;
#[test]
fn get_cloud_env_recovers_from_poisoned_lock() {
let _ = get_cloud_env();
let _ = std::thread::spawn(|| {
let _w = RESULT.write().expect("acquire write");
panic!("intentional poison for §2.2.6 test");
})
.join();
assert!(
RESULT.is_poisoned(),
"test setup failed: RESULT not poisoned"
);
let env_after_poison = get_cloud_env();
assert_eq!(env_after_poison.provider, env_after_poison.provider);
set_result(CloudEnv::none());
let _ = get_cloud_env();
}
static TEST_LOCK: LazyLock<StdMutex<()>> = LazyLock::new(|| StdMutex::new(()));
fn lock() -> std::sync::MutexGuard<'static, ()> {
match TEST_LOCK.lock() {
Ok(g) => g,
Err(p) => p.into_inner(),
}
}
const ALL_CLOUD_ENV_VARS: &[&str] = &[
"AWS_LAMBDA_FUNCTION_NAME",
"AWS_EXECUTION_ENV",
"AWS_REGION",
"AWS_DEFAULT_REGION",
"ECS_CONTAINER_METADATA_URI_V4",
"ECS_CONTAINER_METADATA_URI",
"WEBSITE_SITE_NAME",
"FUNCTIONS_WORKER_RUNTIME",
"CONTAINER_APP_NAME",
"REGION_NAME",
"CONTAINER_APP_HOSTNAME",
"CONTAINER_APP_ENV_DNS_SUFFIX",
"K_SERVICE",
"K_CONFIGURATION",
"GAE_ENV",
"FUNCTION_TARGET",
"FUNCTION_NAME",
"FLY_REGION",
"FLY_APP_NAME",
"VERCEL",
"VERCEL_REGION",
"VERCEL_ENV",
"MODAL_TASK_ID",
"MODAL_IMAGE_ID",
"MODAL_REGION",
"RUNPOD_POD_ID",
"RUNPOD_POD_HOSTNAME",
"RUNPOD_DC_ID",
"REPLICATE_MODEL_ID",
"REPLICATE_DEPLOYMENT_ID",
"RENDER",
"RENDER_SERVICE_ID",
"RENDER_REGION",
"RAILWAY_PROJECT_ID",
"RAILWAY_ENVIRONMENT_ID",
"RAILWAY_REGION",
"RAILWAY_REPLICA_REGION",
"DYNO",
"HEROKU_APP_NAME",
"KOYEB_SERVICE_NAME",
"KOYEB_APP_NAME",
"KOYEB_REGION",
"NETLIFY",
"NETLIFY_SITE_ID",
"CF_PAGES",
"CLOUDFLARE_ACCOUNT_ID",
];
fn clear_env() {
for v in ALL_CLOUD_ENV_VARS {
unsafe { std::env::remove_var(v) };
}
}
fn set_env(name: &str, value: &str) {
unsafe { std::env::set_var(name, value) };
}
fn full_reset() {
clear_env();
reset_module_for_tests();
clear_dmi_override_for_tests();
clear_probe_overrides_for_tests();
}
fn dmi_fixture(fields: &[(&str, &str)]) {
let owned: Vec<(String, String)> = fields
.iter()
.map(|(k, v)| (k.to_string(), v.to_lowercase()))
.collect();
set_dmi_override_for_tests(move || owned.iter().cloned().collect());
}
#[test]
fn test_aws_lambda_env_resolves_fully() {
let _g = lock();
full_reset();
set_env("AWS_LAMBDA_FUNCTION_NAME", "my-fn");
set_env("AWS_REGION", "us-east-1");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("aws"));
assert_eq!(env.region.as_deref(), Some("us-east-1"));
assert_eq!(env.source, "env");
}
#[test]
fn test_azure_app_service_provider_no_region() {
let _g = lock();
full_reset();
set_env("WEBSITE_SITE_NAME", "x");
set_dmi_override_for_tests(HashMap::new);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("azure"));
assert!(env.region.is_none());
assert_eq!(env.source, "env");
}
#[test]
fn test_gcp_cloud_run_provider_no_region() {
let _g = lock();
full_reset();
set_env("K_SERVICE", "my-svc");
set_dmi_override_for_tests(HashMap::new);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("gcp"));
assert!(env.region.is_none());
assert_eq!(env.source, "env");
}
#[test]
fn test_no_env_no_dmi_returns_undetected() {
let _g = lock();
full_reset();
set_dmi_override_for_tests(HashMap::new);
let env = detect_now();
assert!(env.provider.is_none());
assert!(env.region.is_none());
assert_eq!(env.source, "none");
}
#[test]
fn test_dmi_aws_via_sys_vendor_amazon_ec2() {
let _g = lock();
full_reset();
dmi_fixture(&[("sys_vendor", "Amazon EC2")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("aws"));
assert_eq!(env.source, "dmi");
}
#[test]
fn test_dmi_gcp_via_product_name() {
let _g = lock();
full_reset();
dmi_fixture(&[("product_name", "Google Compute Engine")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("gcp"));
}
#[test]
fn test_dmi_azure_via_chassis_asset_tag() {
let _g = lock();
full_reset();
dmi_fixture(&[(
"chassis_asset_tag",
"7783-7084-3265-9085-8269-3286-77",
)]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("azure"));
}
#[test]
fn test_dmi_azure_via_sys_vendor_microsoft_corporation() {
let _g = lock();
full_reset();
dmi_fixture(&[("sys_vendor", "Microsoft Corporation")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("azure"));
}
#[test]
fn test_dmi_oci_via_chassis_asset_tag_not_sys_vendor() {
let _g = lock();
full_reset();
dmi_fixture(&[("chassis_asset_tag", "OracleCloud.com")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("oci"));
}
#[test]
fn test_dmi_alibaba_via_product_name() {
let _g = lock();
full_reset();
dmi_fixture(&[("product_name", "Alibaba Cloud ECS")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("alibaba"));
}
#[test]
fn test_gcp_path_to_region_zone_form() {
assert_eq!(
gcp_path_to_region("projects/123/zones/us-central1-a", true).as_deref(),
Some("us-central1")
);
assert_eq!(
gcp_path_to_region("us-central1-a", true).as_deref(),
Some("us-central1")
);
assert!(gcp_path_to_region("", true).is_none());
}
#[test]
fn test_gcp_path_to_region_region_form() {
assert_eq!(
gcp_path_to_region("projects/123/regions/us-central1", false).as_deref(),
Some("us-central1")
);
assert_eq!(
gcp_path_to_region("projects/123/regions/europe-west4", false).as_deref(),
Some("europe-west4")
);
}
#[test]
fn test_gcp_probe_prefers_region_endpoint() {
let _g = lock();
full_reset();
let region =
gcp_path_to_region("projects/12345/regions/europe-west4", false);
assert_eq!(region.as_deref(), Some("europe-west4"));
}
#[test]
fn test_gcp_probe_falls_back_to_zone_on_region_failure() {
let _g = lock();
full_reset();
let region =
gcp_path_to_region("projects/12345/zones/us-central1-a", true);
assert_eq!(region.as_deref(), Some("us-central1"));
}
#[test]
fn test_oci_probe_uses_canonical_region_name() {
let _g = lock();
let src = include_str!("cloud_detect.rs");
assert!(
src.contains("/opc/v2/instance/canonicalRegionName"),
"OCI probe must hit /canonicalRegionName, not /region"
);
assert!(!src.contains("/opc/v2/instance/region\""));
}
#[test]
fn test_init_never_blocks_when_metadata_unreachable() {
let _g = lock();
full_reset();
set_dmi_override_for_tests(HashMap::new);
let t0 = Instant::now();
start_background_detection(true);
let elapsed = t0.elapsed();
assert!(
elapsed < Duration::from_millis(50),
"init took {:?}, expected < 50ms",
elapsed
);
}
#[test]
fn test_track_network_false_skips_probe() {
let _g = lock();
full_reset();
start_background_detection(false);
let env = get_cloud_env();
assert_eq!(env.source, "none");
assert!(BG_THREAD.lock().unwrap().is_none());
}
#[test]
fn test_start_with_full_env_does_not_launch_thread() {
let _g = lock();
full_reset();
set_env("AWS_LAMBDA_FUNCTION_NAME", "x");
set_env("AWS_REGION", "eu-west-1");
start_background_detection(true);
let env = get_cloud_env();
assert_eq!(env.provider.as_deref(), Some("aws"));
assert_eq!(env.region.as_deref(), Some("eu-west-1"));
assert!(BG_THREAD.lock().unwrap().is_none());
}
#[test]
fn test_ecs_fargate_metadata_uri_resolves_aws_with_region() {
let _g = lock();
full_reset();
set_env(
"ECS_CONTAINER_METADATA_URI_V4",
"http://169.254.170.2/v4/metadata-id",
);
set_env("AWS_REGION", "ap-south-1");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("aws"));
assert_eq!(env.region.as_deref(), Some("ap-south-1"));
assert_eq!(env.source, "env");
}
#[test]
fn test_ecs_v3_metadata_uri_also_resolves_aws() {
let _g = lock();
full_reset();
set_env("ECS_CONTAINER_METADATA_URI", "http://169.254.170.2/v3/x");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("aws"));
}
#[test]
fn test_azure_container_apps_hostname_yields_region() {
let _g = lock();
full_reset();
set_env("CONTAINER_APP_NAME", "my-app");
set_env(
"CONTAINER_APP_HOSTNAME",
"my-app--abc.proudground-12345.eastus.azurecontainerapps.io",
);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("azure"));
assert_eq!(env.region.as_deref(), Some("eastus"));
assert_eq!(env.source, "env");
}
#[test]
fn test_azure_container_apps_dns_suffix_yields_region() {
let _g = lock();
full_reset();
set_env("CONTAINER_APP_NAME", "my-app");
set_env(
"CONTAINER_APP_ENV_DNS_SUFFIX",
"proudground-12345.westeurope.azurecontainerapps.io",
);
let env = detect_now();
assert_eq!(env.region.as_deref(), Some("westeurope"));
}
#[test]
fn test_azure_region_name_wins_when_both_present() {
let _g = lock();
full_reset();
set_env("CONTAINER_APP_NAME", "x");
set_env("REGION_NAME", "northeurope");
set_env(
"CONTAINER_APP_HOSTNAME",
"x.y.eastus.azurecontainerapps.io",
);
let env = detect_now();
assert_eq!(env.region.as_deref(), Some("northeurope"));
}
#[test]
fn test_gcp_k_configuration_alone_signals_gcp() {
let _g = lock();
full_reset();
set_env("K_CONFIGURATION", "my-config");
set_dmi_override_for_tests(HashMap::new);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("gcp"));
}
#[test]
fn test_bare_aws_region_now_classifies_as_aws() {
let _g = lock();
full_reset();
set_env("AWS_REGION", "us-east-1");
set_dmi_override_for_tests(HashMap::new);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("aws"));
assert_eq!(env.region.as_deref(), Some("us-east-1"));
}
#[test]
fn test_fly_region_env_resolves_provider_and_region() {
let _g = lock();
full_reset();
set_env("FLY_REGION", "iad");
set_env("FLY_APP_NAME", "my-app");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("fly"));
assert_eq!(env.region.as_deref(), Some("iad"));
assert_eq!(env.source, "env");
}
#[test]
fn test_fly_app_name_alone_signals_fly() {
let _g = lock();
full_reset();
set_env("FLY_APP_NAME", "my-app");
set_dmi_override_for_tests(HashMap::new);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("fly"));
}
#[test]
fn test_vercel_region_resolves_provider_and_region() {
let _g = lock();
full_reset();
set_env("VERCEL", "1");
set_env("VERCEL_REGION", "iad1");
set_env("AWS_REGION", "us-east-1"); let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("vercel"));
assert_eq!(env.region.as_deref(), Some("iad1"));
}
#[test]
fn test_dmi_digitalocean_via_sys_vendor() {
let _g = lock();
full_reset();
dmi_fixture(&[("sys_vendor", "DigitalOcean")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("digitalocean"));
}
#[test]
fn test_dmi_hetzner_via_sys_vendor() {
let _g = lock();
full_reset();
dmi_fixture(&[("sys_vendor", "Hetzner")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("hetzner"));
}
#[test]
fn test_dmi_vultr_via_sys_vendor() {
let _g = lock();
full_reset();
dmi_fixture(&[("sys_vendor", "Vultr")]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("vultr"));
}
#[test]
fn test_dmi_canonical_field_wins_over_backup() {
let _g = lock();
full_reset();
dmi_fixture(&[
("chassis_asset_tag", "OracleCloud.com"),
("sys_vendor", "Google"),
]);
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("oci"));
}
#[test]
fn test_dmi_unknown_vendor_returns_none() {
let _g = lock();
full_reset();
dmi_fixture(&[("sys_vendor", "LENOVO")]);
let env = detect_now();
assert!(env.provider.is_none());
assert_eq!(env.source, "none");
}
#[test]
fn test_modal_task_id_resolves_modal_with_region() {
let _g = lock();
full_reset();
set_env("MODAL_TASK_ID", "ta-abc");
set_env("MODAL_REGION", "us-east-1");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("modal"));
assert_eq!(env.region.as_deref(), Some("us-east-1"));
}
#[test]
fn test_runpod_pod_id_resolves_provider() {
let _g = lock();
full_reset();
set_env("RUNPOD_POD_ID", "abc123");
set_env("RUNPOD_DC_ID", "US-CA-2");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("runpod"));
assert_eq!(env.region.as_deref(), Some("US-CA-2"));
}
#[test]
fn test_render_resolves() {
let _g = lock();
full_reset();
set_env("RENDER", "true");
set_env("RENDER_SERVICE_ID", "srv-abc");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("render"));
assert!(env.region.is_none());
}
#[test]
fn test_railway_resolves_with_replica_region() {
let _g = lock();
full_reset();
set_env("RAILWAY_PROJECT_ID", "abc");
set_env("RAILWAY_REPLICA_REGION", "us-west2");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("railway"));
assert_eq!(env.region.as_deref(), Some("us-west2"));
}
#[test]
fn test_heroku_dyno_resolves() {
let _g = lock();
full_reset();
set_env("DYNO", "web.1");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("heroku"));
}
#[test]
fn test_koyeb_resolves() {
let _g = lock();
full_reset();
set_env("KOYEB_APP_NAME", "my-app");
set_env("KOYEB_REGION", "fra");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("koyeb"));
assert_eq!(env.region.as_deref(), Some("fra"));
}
#[test]
fn test_phase2_runs_only_aws_gcp_azure_in_parallel() {
assert_eq!(FANOUT_PROBES, &["aws", "gcp", "azure"]);
}
#[test]
fn test_phase2_uses_provider_hint_when_dmi_pre_classifies() {
let _g = lock();
full_reset();
set_probe_override_for_tests("oci", || {
Some(CloudEnv {
provider: Some("oci".into()),
region: Some("us-ashburn-1".into()),
source: "imds",
instance_type: None,
})
});
let aws_called = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
let flag = aws_called.clone();
set_probe_override_for_tests("aws", move || {
flag.store(true, std::sync::atomic::Ordering::SeqCst);
None
});
let env = run_probe(Some("oci"));
assert_eq!(env.provider.as_deref(), Some("oci"));
assert_eq!(env.region.as_deref(), Some("us-ashburn-1"));
assert!(
!aws_called.load(std::sync::atomic::Ordering::SeqCst),
"AWS probe must NOT fire when provider hint is OCI"
);
}
#[test]
fn test_ml_cloud_wins_over_underlying_aws() {
let _g = lock();
full_reset();
set_env("AWS_REGION", "us-east-1");
set_env("MODAL_TASK_ID", "ta-abc");
set_env("MODAL_REGION", "us-east-1");
let env = detect_now();
assert_eq!(env.provider.as_deref(), Some("modal"));
}
#[test]
fn test_cloud_env_struct_carries_instance_type() {
let e = CloudEnv {
provider: Some("aws".into()),
region: Some("us-east-1".into()),
source: "imds",
instance_type: Some("c7g.xlarge".into()),
};
assert_eq!(e.instance_type.as_deref(), Some("c7g.xlarge"));
}
#[test]
fn test_cloud_env_none_has_no_instance_type() {
let e = CloudEnv::none();
assert!(e.instance_type.is_none());
}
#[test]
fn test_aws_probe_override_can_return_instance_type() {
let _g = lock();
full_reset();
set_probe_override_for_tests("aws", || {
Some(CloudEnv {
provider: Some("aws".into()),
region: Some("us-east-1".into()),
source: "imds",
instance_type: Some("c7g.xlarge".into()),
})
});
let env = run_probe(Some("aws"));
assert_eq!(env.provider.as_deref(), Some("aws"));
assert_eq!(env.instance_type.as_deref(), Some("c7g.xlarge"));
}
#[test]
fn test_gcp_probe_override_can_return_machine_type() {
let _g = lock();
full_reset();
set_probe_override_for_tests("gcp", || {
Some(CloudEnv {
provider: Some("gcp".into()),
region: Some("us-central1".into()),
source: "imds",
instance_type: Some("n2-standard-2".into()),
})
});
let env = run_probe(Some("gcp"));
assert_eq!(env.instance_type.as_deref(), Some("n2-standard-2"));
}
#[test]
fn test_azure_probe_override_can_return_vm_size() {
let _g = lock();
full_reset();
set_probe_override_for_tests("azure", || {
Some(CloudEnv {
provider: Some("azure".into()),
region: Some("eastus".into()),
source: "imds",
instance_type: Some("Standard_D2s_v3".into()),
})
});
let env = run_probe(Some("azure"));
assert_eq!(env.instance_type.as_deref(), Some("Standard_D2s_v3"));
}
#[test]
fn test_aws_probe_failure_in_instance_type_keeps_region() {
let _g = lock();
full_reset();
set_probe_override_for_tests("aws", || {
Some(CloudEnv {
provider: Some("aws".into()),
region: Some("us-east-1".into()),
source: "imds",
instance_type: None,
})
});
let env = run_probe(Some("aws"));
assert_eq!(env.region.as_deref(), Some("us-east-1"));
assert!(env.instance_type.is_none());
}
#[test]
fn test_azure_probe_missing_vm_size_keeps_region() {
let _g = lock();
full_reset();
set_probe_override_for_tests("azure", || {
Some(CloudEnv {
provider: Some("azure".into()),
region: Some("eastus".into()),
source: "imds",
instance_type: None,
})
});
let env = run_probe(Some("azure"));
assert_eq!(env.region.as_deref(), Some("eastus"));
assert!(env.instance_type.is_none());
}
#[test]
fn test_env_phase_preserves_no_instance_type() {
let _g = lock();
full_reset();
set_env("AWS_LAMBDA_FUNCTION_NAME", "my-fn");
set_env("AWS_REGION", "us-east-1");
let env = detect_now();
assert!(env.instance_type.is_none());
}
}