syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_006.rs

1//! K8S-OPT-006: Memory request exceeds threshold for workload type.
2
3use super::{OptimizationRule, RuleContext, codes};
4use crate::analyzer::k8s_optimize::config::K8sOptimizeConfig;
5use crate::analyzer::k8s_optimize::parser::parse_memory_to_bytes;
6use crate::analyzer::k8s_optimize::types::{
7    OptimizationIssue, ResourceRecommendation, ResourceSpec, RuleCode, Severity, WorkloadType,
8};
9
10/// Rule: Memory request exceeds threshold.
11pub struct HighMemoryRequestRule;
12
13impl OptimizationRule for HighMemoryRequestRule {
14    fn code(&self) -> &'static str {
15        codes::HIGH_MEMORY_REQUEST
16    }
17
18    fn description(&self) -> &'static str {
19        "Memory request exceeds threshold for workload type"
20    }
21
22    fn default_severity(&self) -> Severity {
23        Severity::High
24    }
25
26    fn check(
27        &self,
28        ctx: &RuleContext,
29        config: &K8sOptimizeConfig,
30    ) -> Option<ResourceRecommendation> {
31        // Exclude database/ML workloads from this check (they legitimately need more memory)
32        if matches!(
33            ctx.workload_type,
34            WorkloadType::Database | WorkloadType::MachineLearning
35        ) {
36            return None;
37        }
38
39        let memory_request = ctx.current.memory_request.as_ref()?;
40        let bytes = parse_memory_to_bytes(memory_request)?;
41        let mi = bytes / (1024 * 1024);
42
43        // Check if exceeds threshold
44        if mi <= config.max_memory_request_mi as u64 {
45            return None;
46        }
47
48        let defaults = ctx.workload_type.default_resources();
49        let recommended = ResourceSpec {
50            cpu_request: None,
51            cpu_limit: None,
52            memory_request: Some(defaults.memory_request.to_string()),
53            memory_limit: Some(defaults.memory_limit.to_string()),
54        };
55
56        Some(ResourceRecommendation {
57            resource_kind: ctx.resource_kind.clone(),
58            resource_name: ctx.resource_name.clone(),
59            namespace: ctx.namespace.clone(),
60            container: ctx.container_name.clone(),
61            file_path: ctx.file_path.clone(),
62            line: ctx.line,
63            issue: OptimizationIssue::OverProvisioned,
64            severity: self.default_severity(),
65            message: format!(
66                "Memory request ({}) exceeds {}Mi threshold for {} workload. This is likely over-provisioned.",
67                memory_request, config.max_memory_request_mi, ctx.workload_type
68            ),
69            workload_type: ctx.workload_type,
70            current: ctx.current.clone(),
71            actual_usage: None,
72            recommended: recommended.clone(),
73            savings: None,
74            fix_yaml: recommended.to_yaml(),
75            rule_code: RuleCode::new(self.code()),
76        })
77    }
78}