syncable_cli/analyzer/kubelint/templates/
antiaffinity.rs1use crate::analyzer::kubelint::context::Object;
4use crate::analyzer::kubelint::context::object::K8sObject;
5use crate::analyzer::kubelint::extract;
6use crate::analyzer::kubelint::templates::{CheckFunc, ParameterDesc, Template, TemplateError};
7use crate::analyzer::kubelint::types::{Diagnostic, ObjectKindsDesc};
8
9pub struct AntiAffinityTemplate;
11
12impl Template for AntiAffinityTemplate {
13 fn key(&self) -> &str {
14 "anti-affinity"
15 }
16
17 fn human_name(&self) -> &str {
18 "Anti-Affinity"
19 }
20
21 fn description(&self) -> &str {
22 "Detects deployments with multiple replicas but no pod anti-affinity"
23 }
24
25 fn supported_object_kinds(&self) -> ObjectKindsDesc {
26 ObjectKindsDesc::default()
27 }
28
29 fn parameters(&self) -> Vec<ParameterDesc> {
30 Vec::new()
31 }
32
33 fn instantiate(
34 &self,
35 _params: &serde_yaml::Value,
36 ) -> Result<Box<dyn CheckFunc>, TemplateError> {
37 Ok(Box::new(AntiAffinityCheck { min_replicas: 2 }))
38 }
39}
40
41struct AntiAffinityCheck {
42 min_replicas: i32,
43}
44
45impl CheckFunc for AntiAffinityCheck {
46 fn check(&self, object: &Object) -> Vec<Diagnostic> {
47 let mut diagnostics = Vec::new();
48
49 let replicas = match &object.k8s_object {
51 K8sObject::Deployment(d) => d.replicas.unwrap_or(1),
52 K8sObject::StatefulSet(d) => d.replicas.unwrap_or(1),
53 K8sObject::ReplicaSet(d) => d.replicas.unwrap_or(1),
54 _ => return diagnostics,
55 };
56
57 if replicas < self.min_replicas {
59 return diagnostics;
60 }
61
62 if let Some(pod_spec) = extract::pod_spec::extract_pod_spec(&object.k8s_object) {
63 let has_anti_affinity = pod_spec
64 .affinity
65 .as_ref()
66 .and_then(|a| a.pod_anti_affinity.as_ref())
67 .map(|paa| {
68 !paa.required_during_scheduling_ignored_during_execution
69 .is_empty()
70 || !paa
71 .preferred_during_scheduling_ignored_during_execution
72 .is_empty()
73 })
74 .unwrap_or(false);
75
76 if !has_anti_affinity {
77 diagnostics.push(Diagnostic {
78 message: format!(
79 "Object '{}' has {} replicas but no pod anti-affinity rules",
80 object.name(),
81 replicas
82 ),
83 remediation: Some(
84 "Add podAntiAffinity rules to spread replicas across nodes for high availability."
85 .to_string(),
86 ),
87 });
88 }
89 }
90
91 diagnostics
92 }
93}