use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct KedaConfig {
pub enabled: bool,
pub min_replicas: u32,
pub max_replicas: u32,
pub polling_interval: u32,
pub cooldown_period: u32,
pub kafka_lag_threshold: u64,
pub activation_lag_threshold: u64,
pub cpu_enabled: bool,
pub cpu_threshold: u32,
pub scaling_pressure_enabled: bool,
pub scaling_pressure_threshold: u32,
}
impl Default for KedaConfig {
fn default() -> Self {
Self {
enabled: true,
min_replicas: 1,
max_replicas: 10,
polling_interval: 15,
cooldown_period: 300,
kafka_lag_threshold: 1000,
activation_lag_threshold: 0,
cpu_enabled: true,
cpu_threshold: 80,
scaling_pressure_enabled: false,
scaling_pressure_threshold: 70,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[non_exhaustive]
pub struct KedaContract {
pub min_replicas: u32,
pub max_replicas: u32,
pub polling_interval: u32,
pub cooldown_period: u32,
pub kafka_lag_threshold: u64,
pub activation_lag_threshold: u64,
pub cpu_enabled: bool,
pub cpu_threshold: u32,
pub scaling_pressure_enabled: bool,
pub scaling_pressure_threshold: u32,
}
impl KedaContract {
#[must_use]
pub fn from_config(config: &KedaConfig) -> Self {
Self {
min_replicas: config.min_replicas,
max_replicas: config.max_replicas,
polling_interval: config.polling_interval,
cooldown_period: config.cooldown_period,
kafka_lag_threshold: config.kafka_lag_threshold,
activation_lag_threshold: config.activation_lag_threshold,
cpu_enabled: config.cpu_enabled,
cpu_threshold: config.cpu_threshold,
scaling_pressure_enabled: config.scaling_pressure_enabled,
scaling_pressure_threshold: config.scaling_pressure_threshold,
}
}
}
impl Default for KedaContract {
fn default() -> Self {
Self::from_config(&KedaConfig::default())
}
}
impl From<&KedaConfig> for KedaContract {
fn from(config: &KedaConfig) -> Self {
Self::from_config(config)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_keda_config_defaults() {
let cfg = KedaConfig::default();
assert!(cfg.enabled);
assert_eq!(cfg.min_replicas, 1);
assert_eq!(cfg.max_replicas, 10);
assert_eq!(cfg.polling_interval, 15);
assert_eq!(cfg.cooldown_period, 300);
assert_eq!(cfg.kafka_lag_threshold, 1000);
assert_eq!(cfg.activation_lag_threshold, 0);
assert!(cfg.cpu_enabled);
assert_eq!(cfg.cpu_threshold, 80);
assert!(!cfg.scaling_pressure_enabled);
assert_eq!(cfg.scaling_pressure_threshold, 70);
}
#[test]
fn test_keda_contract_from_config() {
let cfg = KedaConfig {
kafka_lag_threshold: 5000,
cpu_threshold: 90,
scaling_pressure_enabled: true,
scaling_pressure_threshold: 60,
..Default::default()
};
let contract = KedaContract::from_config(&cfg);
assert_eq!(contract.kafka_lag_threshold, 5000);
assert_eq!(contract.cpu_threshold, 90);
assert!(contract.scaling_pressure_enabled);
assert_eq!(contract.scaling_pressure_threshold, 60);
}
#[test]
fn test_keda_config_serde_roundtrip() {
let cfg = KedaConfig::default();
let yaml = serde_yaml_ng::to_string(&cfg).unwrap();
let parsed: KedaConfig = serde_yaml_ng::from_str(&yaml).unwrap();
assert_eq!(parsed.kafka_lag_threshold, cfg.kafka_lag_threshold);
assert_eq!(
parsed.scaling_pressure_threshold,
cfg.scaling_pressure_threshold
);
}
#[test]
fn test_keda_contract_deser_tolerates_missing_scaling_pressure() {
let legacy = r#"{
"min_replicas": 2,
"max_replicas": 20,
"polling_interval": 15,
"cooldown_period": 300,
"kafka_lag_threshold": 1000,
"activation_lag_threshold": 0,
"cpu_enabled": true,
"cpu_threshold": 80
}"#;
let contract: KedaContract = serde_json::from_str(legacy).unwrap();
assert_eq!(contract.min_replicas, 2);
assert!(!contract.scaling_pressure_enabled);
assert_eq!(contract.scaling_pressure_threshold, 70);
}
}