Skip to main content

resource_tracker/collector/clouds/
alicloud.rs

1use crate::metrics::CloudInfo;
2
3use super::{imds_get, imds_get_headers, new_imds_agent};
4
5fn fetch_imdsv2_token(agent: &ureq::Agent) -> Option<String> {
6    agent
7        .put("http://100.100.100.200/latest/api/token")
8        .header("X-aliyun-ecs-metadata-token-ttl-seconds", "21600")
9        .send_empty()
10        .ok()
11        .and_then(|mut r| {
12            if !r.status().is_success() {
13                return None;
14            }
15            r.body_mut().read_to_string().ok()
16        })
17        .map(|s| s.trim().to_string())
18        .filter(|s| !s.is_empty())
19}
20
21fn imds_get_with_token(agent: &ureq::Agent, path: &str, token: Option<&str>) -> Option<String> {
22    let url = format!("http://100.100.100.200{path}");
23    match token {
24        Some(t) => imds_get_headers(agent, &url, &[("X-aliyun-ecs-metadata-token", t)]),
25        None => imds_get(agent, &url),
26    }
27}
28
29const META_ROOT: &str = "http://100.100.100.200/latest/meta-data/";
30
31/// Alibaba Cloud ECS IMDSv2 (token + header) with IMDSv1 fallback.
32///
33/// Uses `100.100.100.200`, the Alibaba-specific link-local address, as the
34/// confirmation signal. Returns `None` if neither the token PUT nor a plain
35/// GET on the metadata root succeeds.
36///
37/// Reference: <https://www.alibabacloud.com/help/en/ecs/user-guide/view-instance-metadata/>
38pub fn probe() -> Option<CloudInfo> {
39    let agent = new_imds_agent();
40    let token = fetch_imdsv2_token(&agent);
41
42    let read_token: Option<&str> = if token.is_some() {
43        token.as_deref()
44    } else if imds_get(&agent, META_ROOT).is_some() {
45        None
46    } else {
47        return None;
48    };
49
50    let cloud_instance_type = imds_get_with_token(
51        &agent,
52        "/latest/meta-data/instance/instance-type",
53        read_token,
54    );
55    let cloud_region_id = imds_get_with_token(&agent, "/latest/meta-data/region-id", read_token);
56
57    Some(CloudInfo {
58        cloud_vendor_id: Some("alicloud".to_string()),
59        cloud_account_id: None,
60        cloud_region_id: cloud_region_id.filter(|s| !s.is_empty() && s != "unknown"),
61        cloud_zone_id: None,
62        cloud_instance_type: cloud_instance_type.filter(|s| !s.is_empty() && s != "unknown"),
63    })
64}