use crate::Endpoint;
pub fn mint_token() -> String {
let nanos = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map(|d| d.as_nanos()).unwrap_or(0);
format!("ucat_mock_{}_{nanos}", std::process::id())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Heard {
pub requests: u64,
pub account_calls: u64,
}
pub fn heard(endpoint: &Endpoint, token: &str) -> Result<Heard, String> {
let Endpoint::Mock(base) = endpoint else {
return Err("REFUSED [heard-asked-of-the-account] /mock/heard is a door of the mock; the account has none".into());
};
let root = base.as_str().trim_end_matches("/1.3");
let digest = nornir_hash::sha256_hex(token.as_bytes());
let url = format!("{root}/mock/heard?token_sha256={digest}");
let cfg = ureq::Agent::config_builder().http_status_as_error(false).timeout_global(Some(std::time::Duration::from_secs(10))).build();
let mut res = ureq::Agent::new_with_config(cfg).get(&url).call().map_err(|e| format!("GET /mock/heard: {e}"))?;
let status = res.status().as_u16();
let text = res.body_mut().read_to_string().map_err(|e| format!("GET /mock/heard: {e}"))?;
if status != 200 {
return Err(format!("GET /mock/heard answered {status} — {} (a mock without behaviour 63 cannot vouch for a run)", text.trim()));
}
let v: serde_json::Value = serde_json::from_str(&text).map_err(|e| format!("GET /mock/heard: not JSON ({e}): {text}"))?;
Ok(Heard {
requests: v["requests"].as_u64().unwrap_or(0),
account_calls: v["account_calls"].as_u64().unwrap_or(0),
})
}
pub fn require_heard(endpoint: &Endpoint, token: &str, what: &str) -> Result<Heard, String> {
let h = heard(endpoint, token)?;
if h.account_calls == 0 {
return Err(format!(
"REFUSED [mock-never-heard-this-run] before {what}: the mock at {} heard {} request(s) and NO `GET \
/1.3/account` from this run's token. The client that was supposed to be aimed at it spoke to somebody \
else — the likeliest is a terraform provider that no longer honours UPCLOUD_DEBUG_API_BASE_URL, which \
would send this {what} to THE ACCOUNT. Nothing was applied.",
endpoint.base_for_display(),
h.requests
));
}
Ok(h)
}