syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_006.rs1use 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
10pub 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 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 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}