cloud_meta/cloud/
google.rs

1use std::collections::HashMap;
2use hyper::{Body, Method, Request};
3use hyper::body::{to_bytes, Bytes};
4use hyper::client::{Client, HttpConnector};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use crate::Error;
8
9pub struct Google {
10    client:   Client<HttpConnector, Body>,
11    endpoint: String,
12}
13
14#[derive(Debug, Deserialize, Serialize)]
15#[serde(rename_all = "camelCase")]
16pub struct Instance {
17    pub id:           u64,
18    pub name:         String,
19    pub image:        String,
20    pub hostname:     String,
21    pub cpu_platform: String,
22    pub machine_type: String,
23    pub zone:         String,
24
25    #[serde(flatten)]
26    pub extra: HashMap<String, Value>,
27}
28
29impl Google {
30    pub fn new(client: Client<HttpConnector, Body>) -> Self {
31        let endpoint = "http://metadata.google.internal/computeMetadata/v1";
32        Self {
33            client:   client,
34            endpoint: endpoint.to_owned(),
35        }
36    }
37
38    pub async fn instance(&self) -> Result<Instance, Error> {
39        let bytes = self.get("instance/", true).await?;
40        Ok(serde_json::from_slice(&bytes)?)
41    }
42
43    pub async fn get(&self, path: &str, recursive: bool) -> Result<Bytes, Error> {
44        let endpoint = format!("{}/{}?recursive={}", self.endpoint, path, recursive);
45
46        let mut request = Request::new(Body::empty());
47        *request.method_mut() = Method::GET;
48        *request.uri_mut() = endpoint.try_into()?;
49
50        let header = "Metadata-Flavor";
51        let value  = "Google".as_bytes().try_into()?;
52        request.headers_mut().insert(header, value);
53
54        let response = self.client.request(request).await?;
55        if !response.status().is_success() {
56            return Err(response.status().into());
57        }
58
59        Ok(to_bytes(response).await?)
60    }
61}