mod k8s_opt_001;
mod k8s_opt_002;
mod k8s_opt_003;
mod k8s_opt_004;
mod k8s_opt_005;
mod k8s_opt_006;
mod k8s_opt_007;
mod k8s_opt_008;
mod k8s_opt_009;
mod k8s_opt_010;
use crate::analyzer::k8s_optimize::config::K8sOptimizeConfig;
use crate::analyzer::k8s_optimize::types::{
ResourceRecommendation, ResourceSpec, Severity, WorkloadType,
};
use std::path::PathBuf;
pub trait OptimizationRule: Send + Sync {
fn code(&self) -> &'static str;
fn description(&self) -> &'static str;
fn default_severity(&self) -> Severity;
fn check(
&self,
ctx: &RuleContext,
config: &K8sOptimizeConfig,
) -> Option<ResourceRecommendation>;
}
pub struct RuleContext {
pub resource_kind: String,
pub resource_name: String,
pub namespace: Option<String>,
pub container_name: String,
pub file_path: PathBuf,
pub line: Option<u32>,
pub current: ResourceSpec,
pub workload_type: WorkloadType,
}
pub mod codes {
pub const NO_CPU_REQUEST: &str = "K8S-OPT-001";
pub const NO_MEMORY_REQUEST: &str = "K8S-OPT-002";
pub const NO_CPU_LIMIT: &str = "K8S-OPT-003";
pub const NO_MEMORY_LIMIT: &str = "K8S-OPT-004";
pub const HIGH_CPU_REQUEST: &str = "K8S-OPT-005";
pub const HIGH_MEMORY_REQUEST: &str = "K8S-OPT-006";
pub const EXCESSIVE_CPU_RATIO: &str = "K8S-OPT-007";
pub const EXCESSIVE_MEMORY_RATIO: &str = "K8S-OPT-008";
pub const REQUESTS_EQUAL_LIMITS: &str = "K8S-OPT-009";
pub const UNBALANCED_RESOURCES: &str = "K8S-OPT-010";
}
pub fn all_rules() -> Vec<Box<dyn OptimizationRule>> {
vec![
Box::new(k8s_opt_001::NoCpuRequestRule),
Box::new(k8s_opt_002::NoMemoryRequestRule),
Box::new(k8s_opt_003::NoCpuLimitRule),
Box::new(k8s_opt_004::NoMemoryLimitRule),
Box::new(k8s_opt_005::HighCpuRequestRule),
Box::new(k8s_opt_006::HighMemoryRequestRule),
Box::new(k8s_opt_007::ExcessiveCpuRatioRule),
Box::new(k8s_opt_008::ExcessiveMemoryRatioRule),
Box::new(k8s_opt_009::RequestsEqualLimitsRule),
Box::new(k8s_opt_010::UnbalancedResourcesRule),
]
}
pub fn rule_description(code: &str) -> &'static str {
match code {
codes::NO_CPU_REQUEST => "No CPU request defined",
codes::NO_MEMORY_REQUEST => "No memory request defined",
codes::NO_CPU_LIMIT => "No CPU limit defined",
codes::NO_MEMORY_LIMIT => "No memory limit defined",
codes::HIGH_CPU_REQUEST => "CPU request exceeds threshold for workload type",
codes::HIGH_MEMORY_REQUEST => "Memory request exceeds threshold for workload type",
codes::EXCESSIVE_CPU_RATIO => "CPU limit to request ratio is excessive",
codes::EXCESSIVE_MEMORY_RATIO => "Memory limit to request ratio is excessive",
codes::REQUESTS_EQUAL_LIMITS => "Requests equal limits (no bursting allowed)",
codes::UNBALANCED_RESOURCES => "Resource allocation is unbalanced for workload type",
_ => "Unknown rule",
}
}
pub type ContainerContext = RuleContext;
pub fn generate_recommendations(
ctx: &RuleContext,
config: &K8sOptimizeConfig,
) -> Vec<ResourceRecommendation> {
let mut recommendations = Vec::new();
if !ctx.current.has_requests() && !ctx.current.has_limits() {
let defaults = ctx.workload_type.default_resources();
let recommended = ResourceSpec {
cpu_request: Some(defaults.cpu_request.to_string()),
cpu_limit: Some(defaults.cpu_limit.to_string()),
memory_request: Some(defaults.memory_request.to_string()),
memory_limit: Some(defaults.memory_limit.to_string()),
};
recommendations.push(ResourceRecommendation {
resource_kind: ctx.resource_kind.clone(),
resource_name: ctx.resource_name.clone(),
namespace: ctx.namespace.clone(),
container: ctx.container_name.clone(),
file_path: ctx.file_path.clone(),
line: ctx.line,
issue: crate::analyzer::k8s_optimize::types::OptimizationIssue::NoRequestsDefined,
severity: Severity::Critical,
message: "No resource requests defined. This can lead to resource contention, unpredictable scheduling, and OOM kills.".to_string(),
workload_type: ctx.workload_type,
current: ctx.current.clone(),
actual_usage: None,
recommended: recommended.clone(),
savings: None,
fix_yaml: recommended.to_yaml(),
rule_code: crate::analyzer::k8s_optimize::types::RuleCode::new(codes::NO_CPU_REQUEST),
});
return recommendations;
}
for rule in all_rules() {
if config.should_ignore_rule(rule.code()) {
continue;
}
if let Some(rec) = rule.check(ctx, config) {
if rec.severity >= config.min_severity {
recommendations.push(rec);
}
}
}
recommendations
}
pub use k8s_opt_001::NoCpuRequestRule;
pub use k8s_opt_002::NoMemoryRequestRule;
pub use k8s_opt_003::NoCpuLimitRule;
pub use k8s_opt_004::NoMemoryLimitRule;
pub use k8s_opt_005::HighCpuRequestRule;
pub use k8s_opt_006::HighMemoryRequestRule;
pub use k8s_opt_007::ExcessiveCpuRatioRule;
pub use k8s_opt_008::ExcessiveMemoryRatioRule;
pub use k8s_opt_009::RequestsEqualLimitsRule;
pub use k8s_opt_010::UnbalancedResourcesRule;