use axum::{ extract::ws::Message, http::StatusCode, response::{IntoResponse, Response}, Json, }; use serde_json::json; pub type Result = std::result::Result; #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Zone Error: {0:?}")] Zone(String), #[error("Container Error: {0:?}")] Container(String), #[error("Container not found")] NotFound, #[error("WebSocket Error: {0:?}")] WebSocket(#[from] WebSocketError), #[error("Command Error: {0:?}")] Command(#[from] CommandError), #[error("PTY Error: {0:?}")] Pty(#[from] PtyError), #[error("ZFS Error: {0:?}")] ZFS(#[from] zone_zfs::Error), #[error("NSpawn Error: {0:?}")] Nspawn(#[from] zone_nspawn::Error), #[error("Config Error: {0:?}")] Config(#[from] figment::Error), #[error("Axum Error: {0:?}")] Axum(#[from] axum::Error), #[error("Json Error: {0:?}")] Json(#[from] serde_json::error::Error), #[error("Send Error: {0:?}")] Send(#[from] tokio::sync::mpsc::error::SendError), #[error(transparent)] Other(#[from] anyhow::Error), } impl IntoResponse for Error { fn into_response(self) -> Response { let (status, error_message) = match self { Error::Container(source) => (StatusCode::NOT_FOUND, source), err => (StatusCode::INTERNAL_SERVER_ERROR, format!("{}", err)), }; let body = Json(json!({ "error": error_message, })); (status, body).into_response() } } #[derive(thiserror::Error, Debug)] pub enum CommandError { #[error("Command process failed to execute: {0:?}")] Execution(#[from] std::io::Error), #[error("Command process exited with status code: {0:?}")] ExitStatus(i32), #[error("Failed to parse command output: {0:?}")] Parsing(#[from] std::string::FromUtf8Error), } impl From for CommandError { fn from(i: i32) -> Self { Self::ExitStatus(i) } } #[derive(thiserror::Error, Debug)] pub enum PtyError { #[error("Failed to write to PTY: {0:?}")] Write(#[source] std::io::Error), #[error("Failed to read from PTY: {0:?}")] Read(#[source] std::io::Error), #[error("Failed to resize PTY: {0:?}")] Resize(#[source] std::io::Error), } #[derive(thiserror::Error, Debug)] pub enum WebSocketError { #[error("Missing initialization message")] Initialization, #[error("Axum Error: {0:?}")] Axum(#[from] axum::Error), }