pub mod host_executor;
pub mod kernel;
pub mod services;
use async_trait::async_trait;
use console::{Emoji, style};
use std::fmt;
static CHECK: Emoji = Emoji("✅", "[+]");
static WARN: Emoji = Emoji("⚠", "[!]");
static ERROR: Emoji = Emoji("❌", "[X]");
pub enum CheckResultValue {
Passed,
Failed(String),
Errored(String),
Skipped(String),
}
impl fmt::Display for CheckResultValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CheckResultValue::Passed => write!(f, "Passed"),
CheckResultValue::Failed(msg) if msg.is_empty() => write!(f, "Failed"),
CheckResultValue::Failed(msg) => write!(f, "Failed: {msg}"),
CheckResultValue::Errored(msg) if msg.is_empty() => write!(f, "Errored"),
CheckResultValue::Errored(msg) => write!(f, "Errored: {msg}"),
CheckResultValue::Skipped(msg) if msg.is_empty() => write!(f, "Skipped"),
CheckResultValue::Skipped(msg) => write!(f, "Skipped: {msg}"),
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum CheckGroupCategory {
Required,
Optional(String),
Advisory,
}
impl fmt::Display for CheckGroupCategory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CheckGroupCategory::Required => write!(f, "Required"),
CheckGroupCategory::Advisory => write!(f, "Advisory"),
CheckGroupCategory::Optional(_) => write!(f, "Optional"),
}
}
}
pub struct CheckResult {
pub name: String,
pub result: CheckResultValue,
pub output_to_record: Option<String>,
}
impl CheckResult {
pub fn new(name: &str, result: CheckResultValue) -> Self {
Self::new_with_output(name, result, None)
}
pub fn new_with_output(
name: &str,
result: CheckResultValue,
output_to_record: Option<String>,
) -> Self {
Self {
name: name.to_string(),
result,
output_to_record,
}
}
}
pub struct CheckGroupResult {
pub name: String,
pub result: CheckResultValue,
pub results: Vec<CheckResult>,
}
impl CheckGroupResult {
pub fn log_group(&self, category: CheckGroupCategory) {
let name = &self.name;
let result = &self.result;
let s = format!("{}: {}", name, result);
match result {
CheckResultValue::Passed => println!("{} {}", CHECK, style(s).green().bold()),
CheckResultValue::Failed(_) => {
if let CheckGroupCategory::Optional(opt) = &category {
println!(
"{} {}\n{} {} [Optional]",
WARN,
style(opt).yellow().dim(),
WARN,
style(s).yellow().dim()
)
} else {
println!("{} {}", ERROR, style(s).bright().red().bold())
}
}
CheckResultValue::Errored(_) => {
if let CheckGroupCategory::Optional(opt) = &category {
println!(
"{} {}\n{} {} [Optional]",
WARN,
style(opt).yellow().dim(),
WARN,
style(s).yellow().dim()
)
} else {
println!("{} {}", ERROR, style(s).red().bright().bold())
}
}
CheckResultValue::Skipped(reason) => println!(
"{} {} - {}",
WARN,
style(s).yellow().dim(),
style(reason).yellow().dim()
),
}
}
pub fn log_individual_checks(&self) {
for check_result in self.results.iter() {
let name = &check_result.name;
let result = &check_result.result;
let s = format!(" • {}: {}", name, result);
match result {
CheckResultValue::Passed => println!("{}", style(s).magenta().dim()),
CheckResultValue::Failed(_) => println!("{}", style(s).red().dim()),
CheckResultValue::Errored(_) => println!("{}", style(s).red().dim()),
CheckResultValue::Skipped(_) => println!("{}", style(s).yellow().dim()),
}
}
}
}
#[async_trait]
pub trait CheckGroup {
fn name(&self) -> &str;
fn id(&self) -> &str;
fn description(&self) -> &str;
async fn run(&self) -> CheckGroupResult;
fn category(&self) -> CheckGroupCategory;
}