syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_003.rs1use super::{OptimizationRule, RuleContext, codes};
4use crate::analyzer::k8s_optimize::config::K8sOptimizeConfig;
5use crate::analyzer::k8s_optimize::parser::parse_cpu_to_millicores;
6use crate::analyzer::k8s_optimize::types::{
7 OptimizationIssue, ResourceRecommendation, ResourceSpec, RuleCode, Severity,
8};
9
10pub struct NoCpuLimitRule;
12
13impl OptimizationRule for NoCpuLimitRule {
14 fn code(&self) -> &'static str {
15 codes::NO_CPU_LIMIT
16 }
17
18 fn description(&self) -> &'static str {
19 "No CPU limit defined"
20 }
21
22 fn default_severity(&self) -> Severity {
23 Severity::Info
24 }
25
26 fn check(
27 &self,
28 ctx: &RuleContext,
29 config: &K8sOptimizeConfig,
30 ) -> Option<ResourceRecommendation> {
31 if !config.include_info {
33 return None;
34 }
35
36 if ctx.current.cpu_limit.is_some() {
38 return None;
39 }
40
41 let defaults = ctx.workload_type.default_resources();
42
43 let cpu_limit = if let Some(ref cpu_request) = ctx.current.cpu_request {
45 if let Some(millicores) = parse_cpu_to_millicores(cpu_request) {
46 let limit_millicores = millicores * defaults.typical_cpu_ratio as u64;
47 crate::analyzer::k8s_optimize::parser::millicores_to_cpu_string(limit_millicores)
48 } else {
49 defaults.cpu_limit.to_string()
50 }
51 } else {
52 defaults.cpu_limit.to_string()
53 };
54
55 let recommended = ResourceSpec {
56 cpu_request: ctx.current.cpu_request.clone(),
57 cpu_limit: Some(cpu_limit),
58 memory_request: ctx.current.memory_request.clone(),
59 memory_limit: ctx.current.memory_limit.clone(),
60 };
61
62 Some(ResourceRecommendation {
63 resource_kind: ctx.resource_kind.clone(),
64 resource_name: ctx.resource_name.clone(),
65 namespace: ctx.namespace.clone(),
66 container: ctx.container_name.clone(),
67 file_path: ctx.file_path.clone(),
68 line: ctx.line,
69 issue: OptimizationIssue::NoLimitsDefined,
70 severity: self.default_severity(),
71 message: "No CPU limit defined. Consider adding one if you want to prevent CPU starvation on the node.".to_string(),
72 workload_type: ctx.workload_type,
73 current: ctx.current.clone(),
74 actual_usage: None,
75 recommended: recommended.clone(),
76 savings: None,
77 fix_yaml: recommended.to_yaml(),
78 rule_code: RuleCode::new(self.code()),
79 })
80 }
81}