use std::error::Error;
use std::fmt::{Display, Formatter, Result as FResult};
use std::path::PathBuf;
use brane_cfg::node::NodeKind;
use brane_shr::formatters::PrettyListFormatter;
use enum_debug::EnumDebug as _;
use reqwest::StatusCode;
use scylla::transport::errors::NewSessionError;
use specifications::address::Address;
use specifications::version::Version;
#[derive(Debug)]
pub enum ApiError {
ScyllaConnectError { host: Address, err: NewSessionError },
}
impl Display for ApiError {
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
match self {
ApiError::ScyllaConnectError { host, err } => write!(f, "Could not connect to Scylla host '{host}': {err}"),
}
}
}
impl Error for ApiError {}
#[derive(Debug)]
pub enum InfraError {
InfrastructureOpenError { path: PathBuf, err: brane_cfg::infra::Error },
SerializeError { what: &'static str, err: serde_json::Error },
ProxyError { err: brane_prx::errors::ClientError },
RequestError { address: String, err: reqwest::Error },
RequestFailure { address: String, code: StatusCode, message: Option<String> },
ResponseBodyError { address: String, err: reqwest::Error },
ResponseParseError { address: String, raw: String, err: serde_json::Error },
CapabilitiesSerializeError { err: serde_json::Error },
SecretError,
}
impl Display for InfraError {
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
use InfraError::*;
match self {
InfrastructureOpenError { path, err } => write!(f, "Failed to open infrastructure file '{}': {}", path.display(), err),
SerializeError { what, err } => write!(f, "Failed to serialize {what}: {err}"),
ProxyError { err } => write!(f, "Failed to send request through Brane proxy service: {err}"),
RequestError { address, err } => write!(f, "Failed to send GET-request to '{address}': {err}"),
RequestFailure { address, code, message } => write!(
f,
"Request to '{}' failed with status code {} ({}){}",
address,
code,
code.canonical_reason().unwrap_or("???"),
if let Some(err) = message { format!(": {err}") } else { String::new() }
),
ResponseBodyError { address, err } => write!(f, "Failed to get body of response sent by '{address}': {err}"),
ResponseParseError { address, raw, err } => write!(f, "Failed to parse '{raw}' as valid JSON sent by '{address}': {err}"),
CapabilitiesSerializeError { err } => write!(f, "Failed to re-serialize capabilities: {err}"),
SecretError => write!(f, "An internal error has occurred"),
}
}
}
impl Error for InfraError {}
impl warp::reject::Reject for InfraError {}
#[derive(Debug)]
pub enum DataError {
InfrastructureOpenError { path: PathBuf, err: brane_cfg::infra::Error },
InfrastructureLocationsError { path: PathBuf, err: brane_cfg::infra::Error },
InfrastructureMetadataError { path: PathBuf, name: String, err: brane_cfg::infra::Error },
ProxyError { err: brane_prx::client::Error },
RequestError { address: String, err: reqwest::Error },
ResponseBodyError { address: String, err: reqwest::Error },
ResponseParseError { address: String, err: serde_json::Error },
SerializeError { what: &'static str, err: serde_json::Error },
SecretError,
}
impl Display for DataError {
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
use DataError::*;
match self {
InfrastructureOpenError { path, err } => write!(f, "Failed to open infrastructure file '{}': {}", path.display(), err),
InfrastructureLocationsError { path, err } => write!(f, "Failed to get locations from infrastructure file '{}': {}", path.display(), err),
InfrastructureMetadataError { path, name, err } => {
write!(f, "Failed to get metadata of location '{}' from infrastructure file '{}': {}", name, path.display(), err)
},
ProxyError { err } => write!(f, "Failed to prepare sending a request using the proxy service: {err}"),
RequestError { address, err } => write!(f, "Failed to send GET-request to '{address}': {err}"),
ResponseBodyError { address, err } => write!(f, "Failed to get the response body received from '{address}': {err}"),
ResponseParseError { address, err } => write!(f, "Failed to parse response from '{address}' as JSON: {err}"),
SerializeError { what, err } => write!(f, "Failed to serialize {what}: {err}"),
SecretError => write!(f, "An internal error has occurred"),
}
}
}
impl Error for DataError {}
impl warp::reject::Reject for DataError {}
#[derive(Debug)]
pub enum PackageError {
FunctionsSerializeError { name: String, err: serde_json::Error },
TypesSerializeError { name: String, err: serde_json::Error },
MissingDigest { name: String },
PackageTypeDefineError { err: scylla::transport::errors::QueryError },
PackageTableDefineError { err: scylla::transport::errors::QueryError },
PackageInsertError { name: String, err: scylla::transport::errors::QueryError },
VersionsQueryError { name: String, err: scylla::transport::errors::QueryError },
VersionParseError { raw: String, err: specifications::version::ParseError },
NoVersionsFound { name: String },
PathQueryError { name: String, version: Version, err: scylla::transport::errors::QueryError },
UnknownPackage { name: String, version: Version },
FileMetadataError { path: PathBuf, err: std::io::Error },
FileOpenError { path: PathBuf, err: std::io::Error },
FileReadError { path: PathBuf, err: std::io::Error },
FileSendError { path: PathBuf, err: warp::hyper::Error },
NodeConfigLoadError { err: brane_cfg::info::YamlError },
NodeConfigUnexpectedKind { path: PathBuf, got: NodeKind, expected: NodeKind },
TempDirCreateError { err: std::io::Error },
TarCreateError { path: PathBuf, err: std::io::Error },
BodyReadError { err: warp::Error },
TarWriteError { path: PathBuf, err: std::io::Error },
TarFlushError { path: PathBuf, err: std::io::Error },
TarReopenError { path: PathBuf, err: std::io::Error },
TarEntriesError { path: PathBuf, err: std::io::Error },
TarEntryError { path: PathBuf, entry: usize, err: std::io::Error },
TarNotEnoughEntries { path: PathBuf, expected: usize, got: usize },
TarTooManyEntries { path: PathBuf, expected: usize },
TarEntryPathError { path: PathBuf, entry: usize, err: std::io::Error },
TarMissingEntries { expected: Vec<&'static str>, path: PathBuf },
TarFileCloseError { path: PathBuf },
TarFileUnpackError { file: PathBuf, tarball: PathBuf, target: PathBuf, err: std::io::Error },
PackageInfoReadError { path: PathBuf, err: std::io::Error },
PackageInfoParseError { path: PathBuf, err: serde_yaml::Error },
FileMoveError { from: PathBuf, to: PathBuf, err: std::io::Error },
}
impl Display for PackageError {
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
use PackageError::*;
match self {
FunctionsSerializeError { name, err } => write!(f, "Failed to serialize functions in package '{name}': {err}"),
TypesSerializeError { name, err } => write!(f, "Failed to serialize types in package '{name}': {err}"),
MissingDigest { name } => write!(f, "Package '{name}' does not have a digest specified"),
PackageTypeDefineError { err } => write!(f, "Failed to define the 'brane.package' type in the Scylla database: {err}"),
PackageTableDefineError { err } => write!(f, "Failed to define the 'brane.packages' table in the Scylla database: {err}"),
PackageInsertError { name, err } => write!(f, "Failed to insert package '{name}' into the Scylla database: {err}"),
VersionsQueryError { name, err } => write!(f, "Failed to query versions for package '{name}' from the Scylla database: {err}"),
VersionParseError { raw, err } => write!(f, "Failed to parse '{raw}' as a valid version string: {err}"),
NoVersionsFound { name } => write!(f, "No versions found for package '{name}'"),
PathQueryError { name, version, err } => write!(f, "Failed to get path of package '{name}', version {version}: {err}"),
UnknownPackage { name, version } => write!(f, "No package '{name}' exists (or has version {version})"),
FileMetadataError { path, err } => write!(f, "Failed to get metadata of file '{}': {}", path.display(), err),
FileOpenError { path, err } => write!(f, "Failed to open file '{}': {}", path.display(), err),
FileReadError { path, err } => write!(f, "Failed to read file '{}': {}", path.display(), err),
FileSendError { path, err } => write!(f, "Failed to send chunk of file '{}': {}", path.display(), err),
NodeConfigLoadError { err } => write!(f, "Failed to load node config file: {err}"),
NodeConfigUnexpectedKind { path, got, expected } => {
write!(f, "Given node config file '{}' is for a {} node, but expected a {} node", path.display(), got.variant(), expected.variant())
},
TempDirCreateError { err } => write!(f, "Failed to create temporary directory: {err}"),
TarCreateError { path, err } => write!(f, "Failed to create new tar file '{}': {}", path.display(), err),
BodyReadError { err } => write!(f, "Failed to get next chunk in body stream: {err}"),
TarWriteError { path, err } => write!(f, "Failed to write body chunk to tar file '{}': {}", path.display(), err),
TarFlushError { path, err } => write!(f, "Failed to flush new far file '{}': {}", path.display(), err),
TarReopenError { path, err } => write!(f, "Failed to re-open new tar file '{}': {}", path.display(), err),
TarEntriesError { path, err } => write!(f, "Failed to get list of entries in tar file '{}': {}", path.display(), err),
TarEntryError { path, entry, err } => write!(f, "Failed to get entry {} in tar file '{}': {}", entry, path.display(), err),
TarNotEnoughEntries { path, expected, got } => {
write!(f, "Tar file '{}' has only {} entries, but expected {}", path.display(), expected, got)
},
TarTooManyEntries { path, expected } => write!(f, "Tar file '{}' has more than {} entries", path.display(), expected),
TarEntryPathError { path, entry, err } => {
write!(f, "Failed to get the path of entry {} in tar file '{}': {}", entry, path.display(), err)
},
TarMissingEntries { expected, path } => {
write!(f, "Tar file '{}' does not have entries {}", path.display(), PrettyListFormatter::new(expected.iter(), "or"))
},
TarFileCloseError { path } => write!(f, "Failed to close tar file '{}'", path.display()),
TarFileUnpackError { file, tarball, target, err } => {
write!(f, "Failed to extract '{}' file from tar file '{}' to '{}': {}", file.display(), tarball.display(), target.display(), err)
},
PackageInfoReadError { path, err } => write!(f, "Failed to read extracted package info file '{}': {}", path.display(), err),
PackageInfoParseError { path, err } => write!(f, "Failed to parse extracted package info file '{}' as YAML: {}", path.display(), err),
FileMoveError { from, to, err } => write!(f, "Failed to move '{}' to '{}': {}", from.display(), to.display(), err),
}
}
}
impl Error for PackageError {}