use std::collections::HashMap;
use boxlite::{NetworkInfo, NetworkMode};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct CreateBoxRequest {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub image: Option<String>,
#[serde(default)]
pub rootfs_path: Option<String>,
#[serde(default)]
pub cpus: Option<u8>,
#[serde(default)]
pub memory_mib: Option<u32>,
#[serde(default)]
pub disk_size_gb: Option<u64>,
#[serde(default)]
pub working_dir: Option<String>,
#[serde(default)]
pub env: Option<HashMap<String, String>>,
#[serde(default)]
pub entrypoint: Option<Vec<String>>,
#[serde(default)]
pub cmd: Option<Vec<String>>,
#[serde(default)]
pub user: Option<String>,
#[serde(default)]
pub tty: Option<bool>,
#[serde(default)]
pub advanced: CreateBoxAdvancedOptions,
#[serde(default)]
pub network: Option<NetworkSpec>,
#[serde(default)]
pub auto_stop: Option<u32>,
#[serde(default)]
pub auto_delete: Option<u32>,
#[serde(default)]
pub auto_resume: Option<bool>,
#[serde(default)]
pub detach: Option<bool>,
#[serde(default)]
pub secrets: Option<Vec<SecretSpecRequest>>,
#[serde(default)]
pub volumes: Option<Vec<serde_json::Value>>,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct SecretSpecRequest {
pub name: String,
pub value: String,
#[serde(default)]
pub hosts: Vec<String>,
#[serde(default)]
pub placeholder: Option<String>,
}
#[derive(Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub(super) struct CreateBoxAdvancedOptions {
pub capabilities: Option<ContainerCapabilitiesRequest>,
}
#[derive(Clone, Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub(super) struct ContainerCapabilitiesRequest {
pub add: Vec<String>,
pub drop: Vec<String>,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct NetworkSpec {
#[serde(default)]
pub outbound: Option<OutboundNetworkSpec>,
#[serde(default)]
pub inbound: Option<InboundNetworkSpec>,
#[serde(flatten)]
pub legacy: LegacyNetworkSpec,
}
impl NetworkSpec {
pub(super) fn uses_legacy_fields(&self) -> bool {
self.legacy.mode.is_some() || self.legacy.allow_net.is_some()
}
}
#[derive(Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct LegacyNetworkSpec {
#[serde(default)]
pub mode: Option<String>,
#[serde(default)]
pub allow_net: Option<Vec<String>>,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct OutboundNetworkSpec {
pub mode: String,
#[serde(default)]
pub allow_net: Vec<String>,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct InboundNetworkSpec {
pub mode: String,
#[serde(default)]
pub allow_net: Vec<String>,
}
#[derive(Serialize)]
pub(super) struct BoxResponse {
pub box_id: String,
pub name: Option<String>,
pub status: String,
pub created_at: String,
pub updated_at: String,
pub pid: Option<u32>,
pub image: String,
pub cpus: u8,
pub memory_mib: u32,
pub labels: HashMap<String, String>,
pub auto_stop: u32,
pub auto_delete: u32,
pub auto_resume: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub exit_code: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub network: Option<NetworkInfoResponse>,
}
#[derive(Serialize)]
pub(super) struct NetworkInfoResponse {
pub outbound: NetworkDirectionResponse,
pub inbound: NetworkDirectionResponse,
}
#[derive(Serialize)]
pub(super) struct NetworkDirectionResponse {
pub mode: NetworkMode,
pub allow_net: Vec<String>,
}
impl From<&NetworkInfo> for NetworkInfoResponse {
fn from(network: &NetworkInfo) -> Self {
Self {
outbound: NetworkDirectionResponse {
mode: network.outbound.mode.clone(),
allow_net: network.outbound.allow_net.clone(),
},
inbound: NetworkDirectionResponse {
mode: network.inbound.mode.clone(),
allow_net: network.inbound.allow_net.clone(),
},
}
}
}
#[derive(Serialize)]
pub(super) struct ListBoxesResponse {
pub boxes: Vec<BoxResponse>,
}
#[derive(Serialize)]
pub(super) struct VolumeResponse {
pub id: String,
pub name: String,
pub created_at: String,
pub size_bytes: Option<u64>,
}
#[derive(Deserialize, Default)]
pub(super) struct CreateVolumeRequest {
#[serde(default)]
pub name: Option<String>,
}
#[derive(Serialize)]
pub(super) struct ListVolumesResponse {
pub volumes: Vec<VolumeResponse>,
}
#[derive(Serialize)]
pub(super) struct ImageInfoResponse {
pub reference: String,
pub repository: String,
pub tag: String,
pub id: String,
pub cached_at: String,
pub size_bytes: Option<u64>,
}
#[derive(Serialize)]
pub(super) struct ListImagesResponse {
pub images: Vec<ImageInfoResponse>,
}
#[derive(Serialize)]
pub(super) struct ImageVersionResponse {
pub digest: String,
pub size_bytes: Option<u64>,
pub source_ref: String,
pub recorded_at: String,
pub aliases: Vec<String>,
pub last_used_at: Option<String>,
pub upstream_missing_at: Option<String>,
}
#[derive(Serialize)]
pub(super) struct ImageAliasEventResponse {
pub alias: String,
pub from_digest: Option<String>,
pub to_digest: String,
pub actor: Option<String>,
pub recorded_at: String,
}
#[derive(Serialize)]
pub(super) struct ImageDetailResponse {
pub name: String,
pub aliases: Vec<String>,
pub curated: bool,
pub versions: Vec<ImageVersionResponse>,
pub history: Vec<ImageAliasEventResponse>,
}
#[derive(Deserialize)]
pub(super) struct CreateAliasRequest {
pub alias: String,
pub digest: String,
}
#[derive(Serialize)]
pub(super) struct ImageUsageResponse {
pub count: u64,
pub limit: u64,
pub known_bytes: u64,
}
#[derive(Deserialize)]
pub(super) struct ExecRequest {
pub command: String,
#[serde(default)]
pub args: Vec<String>,
#[serde(default)]
pub stdin: Option<String>,
#[serde(default)]
pub env: Option<HashMap<String, String>>,
#[serde(default)]
pub timeout_seconds: Option<f64>,
#[serde(default)]
pub working_dir: Option<String>,
#[serde(default)]
pub tty: bool,
#[serde(default)]
pub user: Option<String>,
}
#[derive(Serialize)]
pub(super) struct ExecResponse {
pub execution_id: String,
}
#[derive(Deserialize)]
pub(super) struct SignalRequest {
pub signal: i32,
}
#[derive(Deserialize)]
pub(super) struct ResizeRequest {
pub cols: u32,
pub rows: u32,
}
#[derive(Serialize)]
pub(super) struct ServerConfig {
pub capabilities: ServerCapabilities,
}
#[derive(Serialize)]
pub(super) struct ServerCapabilities {
pub linux_capabilities_enabled: bool,
pub snapshots_enabled: bool,
pub clone_enabled: bool,
pub export_enabled: bool,
pub import_enabled: bool,
pub exec_user_enabled: bool,
}
#[derive(Deserialize)]
pub(super) struct CreateSnapshotRequest {
pub name: String,
}
#[derive(Serialize)]
pub(super) struct SnapshotResponse {
pub id: String,
pub box_id: String,
pub name: String,
pub created_at: i64,
pub container_disk_bytes: u64,
pub size_bytes: u64,
}
#[derive(Serialize)]
pub(super) struct ListSnapshotsResponse {
pub snapshots: Vec<SnapshotResponse>,
}
#[derive(Deserialize)]
pub(super) struct CloneRequest {
#[serde(default)]
pub name: Option<String>,
}
#[derive(Deserialize)]
pub(super) struct ImportQuery {
#[serde(default)]
pub name: Option<String>,
}
#[derive(Serialize)]
pub(super) struct RuntimeMetricsResponse {
pub boxes_created_total: u64,
pub boxes_failed_total: u64,
pub boxes_stopped_total: u64,
pub num_running_boxes: u64,
pub total_commands_executed: u64,
pub total_exec_errors: u64,
}
#[derive(Serialize)]
pub(super) struct BoxMetricsResponse {
pub commands_executed_total: u64,
pub exec_errors_total: u64,
pub bytes_sent_total: u64,
pub bytes_received_total: u64,
pub cpu_percent: Option<f32>,
pub memory_bytes: Option<u64>,
pub network_bytes_sent: Option<u64>,
pub network_bytes_received: Option<u64>,
pub network_tcp_connections: Option<u64>,
pub network_tcp_errors: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub boot_timing: Option<BootTimingResponse>,
}
#[derive(Serialize)]
pub(super) struct BootTimingResponse {
pub total_create_ms: Option<u64>,
pub guest_boot_ms: Option<u64>,
pub filesystem_setup_ms: Option<u64>,
pub image_prepare_ms: Option<u64>,
pub guest_rootfs_ms: Option<u64>,
pub box_config_ms: Option<u64>,
pub box_spawn_ms: Option<u64>,
pub container_init_ms: Option<u64>,
}
#[derive(Serialize)]
pub(super) struct ErrorBody {
pub error: ErrorDetail,
}
#[derive(Serialize)]
pub(super) struct ErrorDetail {
pub message: String,
#[serde(rename = "type")]
pub error_type: String,
pub code: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub request_id: Option<String>,
}
#[derive(Deserialize)]
pub(super) struct RemoveQuery {
#[serde(default)]
pub force: Option<bool>,
}
#[derive(Deserialize)]
pub(super) struct FileQuery {
pub path: String,
}