Skip to main content

squib_api/schemas/
actions.rs

1//! `/actions` PUT body.
2//!
3//! Per [21-api-compat-matrix.md `/actions`
4//! PUT](../../../specs/21-api-compat-matrix.md#actions-put):
5//!
6//! - `InstanceStart` — `F`.
7//! - `FlushMetrics` — `F`.
8//! - `SendCtrlAltDel` — `R` (x86-only; rejected with `fault_message`).
9
10use serde::{Deserialize, Serialize};
11
12/// Action verb upstream Firecracker supports on `/actions`.
13#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
14pub enum InstanceAction {
15    /// Start the microVM (boot orchestration).
16    InstanceStart,
17    /// Flush queued metrics to the metrics destination.
18    FlushMetrics,
19    /// `Ctrl+Alt+Del` — x86-only; rejected on aarch64.
20    SendCtrlAltDel,
21}
22
23/// Raw `/actions` PUT body off the wire.
24#[derive(Debug, Clone, Deserialize)]
25#[serde(deny_unknown_fields)]
26pub struct RawInstanceActionInfo {
27    /// Action to dispatch.
28    pub action_type: InstanceAction,
29}
30
31/// Validated `/actions` PUT body. The `SendCtrlAltDel` rejection happens at the
32/// controller (so the wire shape stays compatible with x86-only Firecracker SDKs that
33/// might post the verb without checking architecture).
34#[derive(Debug, Clone, Serialize)]
35#[non_exhaustive]
36pub struct InstanceActionInfo {
37    /// Action to dispatch.
38    pub action_type: InstanceAction,
39}
40
41impl From<RawInstanceActionInfo> for InstanceActionInfo {
42    fn from(raw: RawInstanceActionInfo) -> Self {
43        Self {
44            action_type: raw.action_type,
45        }
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_should_deserialize_instance_start_pascal_case() {
55        let json = r#"{"action_type":"InstanceStart"}"#;
56        let raw: RawInstanceActionInfo = serde_json::from_str(json).unwrap();
57        assert_eq!(raw.action_type, InstanceAction::InstanceStart);
58    }
59
60    #[test]
61    fn test_should_deserialize_send_ctrl_alt_del_for_arch_rejection_downstream() {
62        let json = r#"{"action_type":"SendCtrlAltDel"}"#;
63        let raw: RawInstanceActionInfo = serde_json::from_str(json).unwrap();
64        assert_eq!(raw.action_type, InstanceAction::SendCtrlAltDel);
65    }
66
67    #[test]
68    fn test_should_reject_unknown_action() {
69        let json = r#"{"action_type":"Frobnicate"}"#;
70        assert!(serde_json::from_str::<RawInstanceActionInfo>(json).is_err());
71    }
72}