syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_007.rs

1//! K8S-OPT-007: CPU limit to request ratio is excessive.
2
3use super::{OptimizationRule, RuleContext, codes};
4use crate::analyzer::k8s_optimize::config::K8sOptimizeConfig;
5use crate::analyzer::k8s_optimize::parser::{
6    cpu_limit_to_request_ratio, millicores_to_cpu_string, parse_cpu_to_millicores,
7};
8use crate::analyzer::k8s_optimize::types::{
9    OptimizationIssue, ResourceRecommendation, ResourceSpec, RuleCode, Severity,
10};
11
12/// Rule: Excessive CPU limit to request ratio.
13pub struct ExcessiveCpuRatioRule;
14
15impl OptimizationRule for ExcessiveCpuRatioRule {
16    fn code(&self) -> &'static str {
17        codes::EXCESSIVE_CPU_RATIO
18    }
19
20    fn description(&self) -> &'static str {
21        "CPU limit to request ratio is excessive"
22    }
23
24    fn default_severity(&self) -> Severity {
25        Severity::Medium
26    }
27
28    fn check(
29        &self,
30        ctx: &RuleContext,
31        config: &K8sOptimizeConfig,
32    ) -> Option<ResourceRecommendation> {
33        let ratio = cpu_limit_to_request_ratio(&ctx.current)?;
34
35        // Check if exceeds threshold
36        if ratio <= config.max_cpu_limit_ratio as f64 {
37            return None;
38        }
39
40        // Calculate balanced CPU limit
41        let cpu_limit = if let Some(ref cpu_request) = ctx.current.cpu_request {
42            if let Some(millicores) = parse_cpu_to_millicores(cpu_request) {
43                let limit_millicores = millicores * config.max_cpu_limit_ratio as u64;
44                millicores_to_cpu_string(limit_millicores)
45            } else {
46                ctx.current.cpu_limit.clone().unwrap_or_default()
47            }
48        } else {
49            ctx.current.cpu_limit.clone().unwrap_or_default()
50        };
51
52        let recommended = ResourceSpec {
53            cpu_request: ctx.current.cpu_request.clone(),
54            cpu_limit: Some(cpu_limit),
55            memory_request: ctx.current.memory_request.clone(),
56            memory_limit: ctx.current.memory_limit.clone(),
57        };
58
59        Some(ResourceRecommendation {
60            resource_kind: ctx.resource_kind.clone(),
61            resource_name: ctx.resource_name.clone(),
62            namespace: ctx.namespace.clone(),
63            container: ctx.container_name.clone(),
64            file_path: ctx.file_path.clone(),
65            line: ctx.line,
66            issue: OptimizationIssue::ExcessiveRatio,
67            severity: self.default_severity(),
68            message: format!(
69                "CPU limit to request ratio is {:.1}x (threshold: {}x). Large ratios can indicate over-provisioned limits.",
70                ratio, config.max_cpu_limit_ratio
71            ),
72            workload_type: ctx.workload_type,
73            current: ctx.current.clone(),
74            actual_usage: None,
75            recommended: recommended.clone(),
76            savings: None,
77            fix_yaml: recommended.to_yaml(),
78            rule_code: RuleCode::new(self.code()),
79        })
80    }
81}