firecracker_http_client/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use crate::{action::InstanceActionInfo, error::FirecrackerError};
use reqwest::{Client, StatusCode};
use url::Url;

#[cfg(test)]
mod tests;

pub mod action;
pub mod balloon;
pub mod boot;
pub mod cpu;
pub mod drive;
pub mod entropy;
pub mod error;
pub mod instance;
pub mod logger;
pub mod machine;
pub mod metrics;
pub mod mmds;
pub mod models;
pub mod network;
pub mod snapshot;
pub mod validation;
pub mod version;
pub mod vm;
pub mod vsock;

pub use drive::DriveOperations;
pub use models::*;
pub use network::NetworkInterfaceOperations;
pub use snapshot::SnapshotOperations;
pub use vm::VmOperations;

pub struct FirecrackerClient {
    base_url: String,
    client: Client,
}

impl FirecrackerClient {
    pub async fn new(base_url: &str) -> Result<Self, FirecrackerError> {
        Ok(Self {
            base_url: base_url.to_string(),
            client: Client::new(),
        })
    }

    pub(crate) fn url(&self, path: &str) -> Result<Url, FirecrackerError> {
        let url = format!(
            "{}/{}",
            self.base_url.trim_end_matches('/'),
            path.trim_start_matches('/')
        );
        Url::parse(&url).map_err(FirecrackerError::UrlParseError)
    }

    pub async fn create_sync_action(
        &self,
        action: &InstanceActionInfo,
    ) -> Result<(), FirecrackerError> {
        let url = self.url("/actions")?;

        let response = self.client.put(url).json(&action).send().await?;

        match response.status() {
            StatusCode::NO_CONTENT => Ok(()),
            status => {
                let error_msg = response.text().await?;
                Err(FirecrackerError::Api {
                    status_code: status.as_u16(),
                    message: error_msg,
                })
            }
        }
    }
}