syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_004.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,
8};
9
10pub struct NoMemoryLimitRule;
12
13impl OptimizationRule for NoMemoryLimitRule {
14 fn code(&self) -> &'static str {
15 codes::NO_MEMORY_LIMIT
16 }
17
18 fn description(&self) -> &'static str {
19 "No memory limit defined"
20 }
21
22 fn default_severity(&self) -> Severity {
23 Severity::Medium
24 }
25
26 fn check(
27 &self,
28 ctx: &RuleContext,
29 _config: &K8sOptimizeConfig,
30 ) -> Option<ResourceRecommendation> {
31 if ctx.current.memory_limit.is_some() {
33 return None;
34 }
35
36 let defaults = ctx.workload_type.default_resources();
37
38 let memory_limit = if let Some(ref memory_request) = ctx.current.memory_request {
40 if let Some(bytes) = parse_memory_to_bytes(memory_request) {
41 let limit_bytes = (bytes as f64 * defaults.typical_memory_ratio) as u64;
42 crate::analyzer::k8s_optimize::parser::bytes_to_memory_string(limit_bytes)
43 } else {
44 defaults.memory_limit.to_string()
45 }
46 } else {
47 defaults.memory_limit.to_string()
48 };
49
50 let recommended = ResourceSpec {
51 cpu_request: ctx.current.cpu_request.clone(),
52 cpu_limit: ctx.current.cpu_limit.clone(),
53 memory_request: ctx.current.memory_request.clone(),
54 memory_limit: Some(memory_limit),
55 };
56
57 Some(ResourceRecommendation {
58 resource_kind: ctx.resource_kind.clone(),
59 resource_name: ctx.resource_name.clone(),
60 namespace: ctx.namespace.clone(),
61 container: ctx.container_name.clone(),
62 file_path: ctx.file_path.clone(),
63 line: ctx.line,
64 issue: OptimizationIssue::NoLimitsDefined,
65 severity: self.default_severity(),
66 message:
67 "No memory limit defined. Runaway memory usage can affect other pods on the node."
68 .to_string(),
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}