syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_002.rs

1//! K8S-OPT-002: No memory request defined.
2
3use super::{OptimizationRule, RuleContext, codes};
4use crate::analyzer::k8s_optimize::config::K8sOptimizeConfig;
5use crate::analyzer::k8s_optimize::types::{
6    OptimizationIssue, ResourceRecommendation, ResourceSpec, RuleCode, Severity,
7};
8
9/// Rule: No memory request defined.
10pub struct NoMemoryRequestRule;
11
12impl OptimizationRule for NoMemoryRequestRule {
13    fn code(&self) -> &'static str {
14        codes::NO_MEMORY_REQUEST
15    }
16
17    fn description(&self) -> &'static str {
18        "No memory request defined"
19    }
20
21    fn default_severity(&self) -> Severity {
22        Severity::High
23    }
24
25    fn check(
26        &self,
27        ctx: &RuleContext,
28        _config: &K8sOptimizeConfig,
29    ) -> Option<ResourceRecommendation> {
30        // Skip if memory request is defined
31        if ctx.current.memory_request.is_some() {
32            return None;
33        }
34
35        // Skip if no resources at all (handled separately as critical)
36        if !ctx.current.has_any() {
37            return None;
38        }
39
40        let defaults = ctx.workload_type.default_resources();
41        let recommended = ResourceSpec {
42            cpu_request: None,
43            cpu_limit: None,
44            memory_request: Some(defaults.memory_request.to_string()),
45            memory_limit: Some(defaults.memory_limit.to_string()),
46        };
47
48        Some(ResourceRecommendation {
49            resource_kind: ctx.resource_kind.clone(),
50            resource_name: ctx.resource_name.clone(),
51            namespace: ctx.namespace.clone(),
52            container: ctx.container_name.clone(),
53            file_path: ctx.file_path.clone(),
54            line: ctx.line,
55            issue: OptimizationIssue::NoRequestsDefined,
56            severity: self.default_severity(),
57            message: "No memory request defined. This can lead to OOM kills and node pressure."
58                .to_string(),
59            workload_type: ctx.workload_type,
60            current: ctx.current.clone(),
61            actual_usage: None,
62            recommended: recommended.clone(),
63            savings: None,
64            fix_yaml: recommended.to_yaml(),
65            rule_code: RuleCode::new(self.code()),
66        })
67    }
68}