syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_004.rs

1//! K8S-OPT-004: No memory limit defined.
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,
8};
9
10/// Rule: No memory limit defined.
11pub 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        // Skip if memory limit is defined
32        if ctx.current.memory_limit.is_some() {
33            return None;
34        }
35
36        let defaults = ctx.workload_type.default_resources();
37
38        // Calculate memory limit based on request if available
39        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}