syncable_cli/analyzer/kubelint/templates/
requirements.rs1use crate::analyzer::kubelint::context::Object;
4use crate::analyzer::kubelint::extract;
5use crate::analyzer::kubelint::templates::{CheckFunc, ParameterDesc, Template, TemplateError};
6use crate::analyzer::kubelint::types::{Diagnostic, ObjectKindsDesc};
7
8pub struct CpuRequirementsTemplate;
10
11impl Template for CpuRequirementsTemplate {
12 fn key(&self) -> &str {
13 "cpu-requirements"
14 }
15
16 fn human_name(&self) -> &str {
17 "CPU Requirements"
18 }
19
20 fn description(&self) -> &str {
21 "Detects containers without CPU requests or limits"
22 }
23
24 fn supported_object_kinds(&self) -> ObjectKindsDesc {
25 ObjectKindsDesc::default()
26 }
27
28 fn parameters(&self) -> Vec<ParameterDesc> {
29 Vec::new()
30 }
31
32 fn instantiate(
33 &self,
34 _params: &serde_yaml::Value,
35 ) -> Result<Box<dyn CheckFunc>, TemplateError> {
36 Ok(Box::new(CpuRequirementsCheck {
37 require_limits: false,
38 }))
39 }
40}
41
42struct CpuRequirementsCheck {
43 require_limits: bool,
44}
45
46impl CheckFunc for CpuRequirementsCheck {
47 fn check(&self, object: &Object) -> Vec<Diagnostic> {
48 let mut diagnostics = Vec::new();
49
50 if let Some(pod_spec) = extract::pod_spec::extract_pod_spec(&object.k8s_object) {
51 for container in extract::container::all_containers(pod_spec) {
52 let has_cpu_request = container
53 .resources
54 .as_ref()
55 .and_then(|r| r.requests.as_ref())
56 .map(|r| r.contains_key("cpu"))
57 .unwrap_or(false);
58
59 let has_cpu_limit = container
60 .resources
61 .as_ref()
62 .and_then(|r| r.limits.as_ref())
63 .map(|r| r.contains_key("cpu"))
64 .unwrap_or(false);
65
66 if !has_cpu_request {
67 diagnostics.push(Diagnostic {
68 message: format!(
69 "Container '{}' does not have a CPU request",
70 container.name
71 ),
72 remediation: Some(
73 "Set resources.requests.cpu for proper scheduling.".to_string(),
74 ),
75 });
76 }
77
78 if self.require_limits && !has_cpu_limit {
79 diagnostics.push(Diagnostic {
80 message: format!(
81 "Container '{}' does not have a CPU limit",
82 container.name
83 ),
84 remediation: Some(
85 "Set resources.limits.cpu to prevent resource exhaustion.".to_string(),
86 ),
87 });
88 }
89 }
90 }
91
92 diagnostics
93 }
94}
95
96pub struct MemoryRequirementsTemplate;
98
99impl Template for MemoryRequirementsTemplate {
100 fn key(&self) -> &str {
101 "memory-requirements"
102 }
103
104 fn human_name(&self) -> &str {
105 "Memory Requirements"
106 }
107
108 fn description(&self) -> &str {
109 "Detects containers without memory requests or limits"
110 }
111
112 fn supported_object_kinds(&self) -> ObjectKindsDesc {
113 ObjectKindsDesc::default()
114 }
115
116 fn parameters(&self) -> Vec<ParameterDesc> {
117 Vec::new()
118 }
119
120 fn instantiate(
121 &self,
122 _params: &serde_yaml::Value,
123 ) -> Result<Box<dyn CheckFunc>, TemplateError> {
124 Ok(Box::new(MemoryRequirementsCheck {
125 require_limits: false,
126 }))
127 }
128}
129
130struct MemoryRequirementsCheck {
131 require_limits: bool,
132}
133
134impl CheckFunc for MemoryRequirementsCheck {
135 fn check(&self, object: &Object) -> Vec<Diagnostic> {
136 let mut diagnostics = Vec::new();
137
138 if let Some(pod_spec) = extract::pod_spec::extract_pod_spec(&object.k8s_object) {
139 for container in extract::container::all_containers(pod_spec) {
140 let has_memory_request = container
141 .resources
142 .as_ref()
143 .and_then(|r| r.requests.as_ref())
144 .map(|r| r.contains_key("memory"))
145 .unwrap_or(false);
146
147 let has_memory_limit = container
148 .resources
149 .as_ref()
150 .and_then(|r| r.limits.as_ref())
151 .map(|r| r.contains_key("memory"))
152 .unwrap_or(false);
153
154 if !has_memory_request {
155 diagnostics.push(Diagnostic {
156 message: format!(
157 "Container '{}' does not have a memory request",
158 container.name
159 ),
160 remediation: Some(
161 "Set resources.requests.memory for proper scheduling.".to_string(),
162 ),
163 });
164 }
165
166 if self.require_limits && !has_memory_limit {
167 diagnostics.push(Diagnostic {
168 message: format!(
169 "Container '{}' does not have a memory limit",
170 container.name
171 ),
172 remediation: Some(
173 "Set resources.limits.memory to prevent OOM kills.".to_string(),
174 ),
175 });
176 }
177 }
178 }
179
180 diagnostics
181 }
182}