#![deny(clippy::wildcard_enum_match_arm)]
use std::fmt;
use engenho_controllers::{
Controller, ControllerType, DnsController, DrvBuildController, DrvController,
EventDrivenController, HorizontalPodAutoscalerController, IngressController, PlantioController,
TieredCacheReconciler,
};
use crate::runtime_health::Relister;
engenho_controllers::closed_enum! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Dormant {
Hpa,
Ingress,
Dns,
Plantio,
Drv,
DrvBuild,
TieredCache,
EventDriven,
RuntimeRelist,
}
}
engenho_controllers::closed_enum! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum DormantReason {
NoMetricsSource,
NoIngressDatapath,
NoDnsResolver,
NoDerivationPlane,
NoRocaPlane,
SupersededByWatchDriver,
NoRuntimeRelist,
}
}
impl Dormant {
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Hpa => "hpa",
Self::Ingress => "ingress",
Self::Dns => "dns",
Self::Plantio => "plantio",
Self::Drv => "drv",
Self::DrvBuild => "drv-build",
Self::TieredCache => "tiered-cache",
Self::EventDriven => "event-driven",
Self::RuntimeRelist => "runtime-relist",
}
}
#[must_use]
pub fn controller_type(self) -> ControllerType {
match self {
Self::Hpa => of::<HorizontalPodAutoscalerController>(),
Self::Ingress => of::<IngressController>(),
Self::Dns => of::<DnsController>(),
Self::Plantio => of::<PlantioController>(),
Self::Drv => of::<DrvController>(),
Self::DrvBuild => of::<DrvBuildController>(),
Self::TieredCache => of::<TieredCacheReconciler>(),
Self::EventDriven => of::<EventDrivenController<()>>(),
Self::RuntimeRelist => of::<Relister>(),
}
}
#[must_use]
pub const fn reason(self) -> DormantReason {
match self {
Self::Hpa => DormantReason::NoMetricsSource,
Self::Ingress => DormantReason::NoIngressDatapath,
Self::Dns => DormantReason::NoDnsResolver,
Self::Plantio => DormantReason::NoRocaPlane,
Self::Drv | Self::DrvBuild | Self::TieredCache => DormantReason::NoDerivationPlane,
Self::EventDriven => DormantReason::SupersededByWatchDriver,
Self::RuntimeRelist => DormantReason::NoRuntimeRelist,
}
}
}
impl fmt::Display for Dormant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
impl fmt::Display for DormantReason {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::NoMetricsSource => "no metrics source: the only MetricsProvider is the test fake",
Self::NoIngressDatapath => {
"no ingress datapath: its backends configure a proxy the binary does not run"
}
Self::NoDnsResolver => "no DNS resolver: its only backend is a zone nothing serves",
Self::NoDerivationPlane => "the derivation plane is assembled by no binary",
Self::NoRocaPlane => {
"the roça plane is assembled only by PlantioPipeline, which no binary calls"
}
Self::SupersededByWatchDriver => "superseded by the runtime's WatchDriver",
Self::NoRuntimeRelist => {
"no container runtime relists yet: the kubelet's ContainerRuntime has no relist"
}
})
}
}
fn of<C: Controller>() -> ControllerType {
ControllerType::of::<C>()
}
#[cfg(test)]
mod tests {
use std::collections::BTreeSet;
use super::*;
#[test]
fn every_row_names_a_different_controller_type() {
let types: BTreeSet<(&str, &str)> = Dormant::ALL
.iter()
.map(|d| (d.controller_type().krate(), d.controller_type().ident()))
.collect();
assert_eq!(types.len(), Dormant::ALL.len(), "two rows name one type");
let names: BTreeSet<&str> = Dormant::ALL.iter().map(|d| d.name()).collect();
assert_eq!(names.len(), Dormant::ALL.len(), "two rows share a name");
}
#[test]
fn every_reason_is_some_rows_reason() {
let given: BTreeSet<DormantReason> = Dormant::ALL.iter().map(|d| d.reason()).collect();
let unused: Vec<DormantReason> = DormantReason::ALL
.iter()
.copied()
.filter(|r| !given.contains(r))
.collect();
assert!(unused.is_empty(), "reasons no row gives: {unused:?}");
}
#[test]
fn the_generic_adapter_is_declared_by_its_own_name() {
let t = Dormant::EventDriven.controller_type();
assert_eq!(
(t.krate(), t.ident()),
("engenho_controllers", "EventDrivenController")
);
}
}