use aide::OperationIo;
use chrono::{DateTime, Utc};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display};
use thiserror::Error;
pub use uuid::Uuid;
use crate::v1alpha1::Probe;
pub type WatchId = Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, OperationIo)]
#[serde(rename_all = "camelCase")]
pub struct Watch {
pub id: WatchId,
pub name: String,
pub owner_ref: String,
pub config: WatchConfig,
pub status: WatchStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct CreateWatch {
pub name: String,
pub owner_ref: String,
pub config: WatchConfig,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, Error)]
#[serde(rename_all = "camelCase")]
pub enum CreateWatchError {
#[error("probes list must not be empty")]
NoProbes,
#[error("alerts list must not be empty")]
NoAlerts,
}
impl CreateWatch {
pub fn try_into_watch(self, id: WatchId) -> Result<Watch, CreateWatchError> {
if self.config.probes.is_empty() {
return Err(CreateWatchError::NoProbes);
}
Ok(Watch {
id,
name: self.name,
status: WatchStatus::default(),
owner_ref: self.owner_ref,
config: self.config,
})
}
}
impl From<Watch> for CreateWatch {
fn from(value: Watch) -> Self {
CreateWatch {
name: value.name,
owner_ref: value.owner_ref,
config: value.config,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct WatchConfig {
pub probes: Vec<Probe>,
}
impl Display for Watch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} ({})", self.name, self.id)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct WatchStatus {
pub state: WatchState,
#[serde(default)]
pub last_update: Option<DateTime<Utc>>,
#[serde(default)]
pub failing_probes: Vec<String>,
}
impl WatchStatus {
pub fn new(state: WatchState, failing_probes: Vec<&Probe>) -> WatchStatus {
WatchStatus {
state,
last_update: Some(Utc::now()),
failing_probes: failing_probes
.into_iter()
.map(|probe| {
probe
.description
.clone()
.unwrap_or_else(|| probe.to_string())
})
.collect(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, Default)]
#[serde(rename_all = "camelCase")]
pub enum WatchState {
#[default]
Pending,
Ok,
Failing,
}
impl Display for WatchState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Pending => "pending",
Self::Ok => "ok",
Self::Failing => "failing",
}
)
}
}