use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InventoryFileKind {
Hosts,
Groups,
Defaults,
}
impl fmt::Display for InventoryFileKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InventoryFileKind::Hosts => write!(f, "hosts"),
InventoryFileKind::Groups => write!(f, "groups"),
InventoryFileKind::Defaults => write!(f, "defaults"),
}
}
}
#[derive(Debug, Clone)]
pub enum InventoryLoadError {
Read {
kind: InventoryFileKind,
path: String,
message: String,
},
ParseJson {
kind: InventoryFileKind,
path: String,
message: String,
},
ParseYaml {
kind: InventoryFileKind,
path: String,
message: String,
},
UnsupportedFormat {
kind: InventoryFileKind,
path: String,
},
TransformPluginNotFound {
name: String,
},
NotTransformPlugin {
name: String,
},
Message(String),
}
impl fmt::Display for InventoryLoadError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InventoryLoadError::Read {
kind,
path,
message,
} => write!(f, "failed to read {kind} inventory file {path}: {message}"),
InventoryLoadError::ParseJson {
kind,
path,
message,
} => write!(
f,
"failed to parse {kind} inventory JSON file {path}: {message}"
),
InventoryLoadError::ParseYaml {
kind,
path,
message,
} => write!(
f,
"failed to parse {kind} inventory YAML file {path}: {message}"
),
InventoryLoadError::UnsupportedFormat { kind, path } => write!(
f,
"unsupported {kind} inventory file format for {path}. Use .json, .yaml, or .yml"
),
InventoryLoadError::TransformPluginNotFound { name } => {
write!(f, "transform plugin '{name}' not found")
}
InventoryLoadError::NotTransformPlugin { name } => {
write!(f, "plugin '{name}' is not a transform function plugin")
}
InventoryLoadError::Message(msg) => write!(f, "{msg}"),
}
}
}
impl std::error::Error for InventoryLoadError {}
impl From<String> for InventoryLoadError {
fn from(value: String) -> Self {
InventoryLoadError::Message(value)
}
}
impl From<&str> for InventoryLoadError {
fn from(value: &str) -> Self {
InventoryLoadError::Message(value.to_string())
}
}
#[derive(Debug, Clone)]
pub enum SshConfigError {
NotFound { path: String },
PermissionDenied { path: String, message: String },
CheckFailed { path: String, message: String },
OpenFailed { path: String, message: String },
ParseFailed { path: String, message: String },
}
impl fmt::Display for SshConfigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SshConfigError::NotFound { path } => write!(f, "SSH config file not found: {path}"),
SshConfigError::PermissionDenied { path, message } => {
write!(
f,
"SSH config file exists but permission denied: {path}: {message}"
)
}
SshConfigError::CheckFailed { path, message } => {
write!(f, "Failed to check SSH config file {path}: {message}")
}
SshConfigError::OpenFailed { path, message } => {
write!(f, "Failed to open SSH config file {path}: {message}")
}
SshConfigError::ParseFailed { path, message } => {
write!(f, "Failed to parse SSH config file {path}: {message}")
}
}
}
}
impl std::error::Error for SshConfigError {}
#[derive(Debug, Clone)]
pub enum ConfigLoadError {
UnsupportedFormat { path: String },
Read { path: String, message: String },
Deserialize { path: String, message: String },
SshConfig(SshConfigError),
}
impl fmt::Display for ConfigLoadError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ConfigLoadError::UnsupportedFormat { path } => {
write!(
f,
"unsupported settings file format for {path}. Use .json, .yaml, or .yml"
)
}
ConfigLoadError::Read { path, message } => {
write!(f, "failed to read settings from {path}: {message}")
}
ConfigLoadError::Deserialize { path, message } => {
write!(f, "failed to deserialize settings from {path}: {message}")
}
ConfigLoadError::SshConfig(err) => write!(f, "{err}"),
}
}
}
impl std::error::Error for ConfigLoadError {}
#[derive(Debug, Clone)]
pub enum GenjaError {
PluginsNotLoaded,
InventoryNotLoaded,
PluginNotFound(String),
NotInventoryPlugin(String),
AsyncInventoryPluginRequiresAsyncConstruction(String),
NotRunnerPlugin(String),
PluginLoad(String),
ConfigLoad(ConfigLoadError),
InventoryLoad(InventoryLoadError),
Message(String),
NotImplemented(&'static str),
}
impl fmt::Display for GenjaError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GenjaError::PluginsNotLoaded => write!(f, "plugins have not been loaded"),
GenjaError::InventoryNotLoaded => write!(f, "inventory has not been loaded"),
GenjaError::PluginNotFound(name) => write!(f, "plugin '{name}' not found"),
GenjaError::NotInventoryPlugin(name) => {
write!(f, "plugin '{name}' is not an inventory plugin")
}
GenjaError::AsyncInventoryPluginRequiresAsyncConstruction(name) => {
write!(
f,
"async inventory plugin '{name}' requires async runtime construction"
)
}
GenjaError::NotRunnerPlugin(name) => {
write!(f, "plugin '{name}' is not a runner plugin")
}
GenjaError::PluginLoad(err) => write!(f, "failed to load plugins: {err}"),
GenjaError::ConfigLoad(err) => write!(f, "failed to load settings: {err}"),
GenjaError::InventoryLoad(err) => write!(f, "failed to load inventory: {err}"),
GenjaError::Message(msg) => write!(f, "{msg}"),
GenjaError::NotImplemented(msg) => write!(f, "{msg}"),
}
}
}
impl std::error::Error for GenjaError {}
impl From<String> for GenjaError {
fn from(value: String) -> Self {
GenjaError::Message(value)
}
}
impl From<&str> for GenjaError {
fn from(value: &str) -> Self {
GenjaError::Message(value.to_string())
}
}
impl From<InventoryLoadError> for GenjaError {
fn from(value: InventoryLoadError) -> Self {
GenjaError::InventoryLoad(value)
}
}
impl From<ConfigLoadError> for GenjaError {
fn from(value: ConfigLoadError) -> Self {
GenjaError::ConfigLoad(value)
}
}