Skip to main content

resource_tracker/collector/clouds/
gcp.rs

1use crate::metrics::CloudInfo;
2
3use super::{imds_get_headers, new_imds_agent};
4
5/// Derive the region from a GCP zone basename (e.g. `us-central1-a` → `us-central1`).
6fn zone_to_region(zone: &str) -> String {
7    match zone.rsplit_once('-') {
8        Some((prefix, _)) => prefix.to_string(),
9        None => zone.to_string(),
10    }
11}
12
13pub fn probe() -> Option<CloudInfo> {
14    let agent = new_imds_agent();
15    const FLAVOR: &[(&str, &str)] = &[("Metadata-Flavor", "Google")];
16    let machine_type = imds_get_headers(
17        &agent,
18        "http://metadata.google.internal/computeMetadata/v1/instance/machine-type",
19        FLAVOR,
20    )?;
21    let zone_full = imds_get_headers(
22        &agent,
23        "http://metadata.google.internal/computeMetadata/v1/instance/zone",
24        FLAVOR,
25    )?;
26
27    // projects/PROJECT_NUM/machineTypes/MACHINE_TYPE
28    let instance_type = machine_type.rsplit('/').next()?.to_string();
29    let zone = zone_full.rsplit('/').next()?.to_string();
30    let cloud_region_id = zone_to_region(&zone);
31
32    Some(CloudInfo {
33        cloud_vendor_id: Some("gcp".to_string()),
34        cloud_account_id: None,
35        cloud_region_id: Some(cloud_region_id),
36        cloud_zone_id: Some(zone),
37        cloud_instance_type: Some(instance_type),
38    })
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn test_zone_to_region() {
47        assert_eq!(zone_to_region("us-central1-a"), "us-central1");
48        assert_eq!(zone_to_region("x"), "x");
49        assert_eq!(zone_to_region("europe-west4-b"), "europe-west4");
50    }
51}