use std::fmt;
use serde::{Deserialize, Serialize};
use crate::api::AdmissionPolicy;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RunningJob {
pub repository: String,
pub runner: String,
pub job: Option<u64>,
}
impl fmt::Display for RunningJob {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.job {
Some(job) => write!(f, "job {job} on {}", self.runner),
None => write!(f, "{}", self.runner),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Busy {
pub message: String,
pub jobs: Vec<RunningJob>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct PauseQuery {
#[serde(default)]
pub force: bool,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Paused {
pub stopped: Vec<RunningJob>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ConfigFile {
pub path: String,
pub text: String,
pub revision: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReplaceQuery {
pub revision: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ConfigCheck {
pub valid: bool,
pub message: String,
pub warnings: Vec<String>,
pub admission: AdmissionPolicy,
pub memory_caps: Option<u64>,
pub memory_needed: Option<u64>,
pub memory_max: Option<u64>,
pub revision: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Doctor {
pub checks: Vec<Check>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Check {
pub name: String,
pub status: CheckStatus,
pub detail: String,
pub fix: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum CheckStatus {
Pass,
Fail,
Warn,
Skip,
Info,
}
impl CheckStatus {
pub fn label(self) -> &'static str {
match self {
CheckStatus::Pass => "ok",
CheckStatus::Fail => "FAIL",
CheckStatus::Warn => "WARN",
CheckStatus::Skip => "skip",
CheckStatus::Info => "info",
}
}
pub fn tone(self) -> super::Tone {
match self {
CheckStatus::Pass => super::Tone::Good,
CheckStatus::Fail => super::Tone::Bad,
CheckStatus::Warn => super::Tone::Warn,
CheckStatus::Skip => super::Tone::Quiet,
CheckStatus::Info => super::Tone::Neutral,
}
}
}
impl Doctor {
pub fn passed(&self) -> bool {
Doctor::all_passed(&self.checks)
}
pub fn all_passed(checks: &[Check]) -> bool {
!checks.iter().any(|check| check.status == CheckStatus::Fail)
}
}
impl fmt::Display for Check {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let status = self.status.label();
write!(f, "{status:<5} {}: {}", self.name, self.detail)?;
if let Some(fix) = &self.fix {
for (i, line) in fix.lines().enumerate() {
let label = if i == 0 { "fix:" } else { "" };
write!(f, "\n {label:<4} {line}")?;
}
}
Ok(())
}
}