firecracker_http_client/
lib.rs

1use crate::{action::InstanceActionInfo, error::FirecrackerError};
2use reqwest::{Client, StatusCode};
3use url::Url;
4
5#[cfg(test)]
6mod tests;
7
8pub mod action;
9pub mod balloon;
10pub mod boot;
11pub mod cpu;
12pub mod drive;
13pub mod entropy;
14pub mod error;
15pub mod instance;
16pub mod logger;
17pub mod machine;
18pub mod metrics;
19pub mod mmds;
20pub mod models;
21pub mod network;
22pub mod snapshot;
23pub mod validation;
24pub mod version;
25pub mod vm;
26pub mod vsock;
27
28pub use drive::DriveOperations;
29pub use models::*;
30pub use network::NetworkInterfaceOperations;
31pub use snapshot::SnapshotOperations;
32pub use vm::VmOperations;
33
34pub struct FirecrackerClient {
35    base_url: String,
36    client: Client,
37}
38
39impl FirecrackerClient {
40    pub async fn new(base_url: &str) -> Result<Self, FirecrackerError> {
41        Ok(Self {
42            base_url: base_url.to_string(),
43            client: Client::new(),
44        })
45    }
46
47    pub(crate) fn url(&self, path: &str) -> Result<Url, FirecrackerError> {
48        let url = format!(
49            "{}/{}",
50            self.base_url.trim_end_matches('/'),
51            path.trim_start_matches('/')
52        );
53        Url::parse(&url).map_err(FirecrackerError::UrlParseError)
54    }
55
56    pub async fn create_sync_action(
57        &self,
58        action: &InstanceActionInfo,
59    ) -> Result<(), FirecrackerError> {
60        let url = self.url("/actions")?;
61
62        let response = self.client.put(url).json(&action).send().await?;
63
64        match response.status() {
65            StatusCode::NO_CONTENT => Ok(()),
66            status => {
67                let error_msg = response.text().await?;
68                Err(FirecrackerError::Api {
69                    status_code: status.as_u16(),
70                    message: error_msg,
71                })
72            }
73        }
74    }
75}