syncable_cli/analyzer/kubelint/templates/
updateconfig.rs

1//! Update strategy detection templates.
2
3use crate::analyzer::kubelint::context::Object;
4use crate::analyzer::kubelint::context::object::K8sObject;
5use crate::analyzer::kubelint::templates::{CheckFunc, ParameterDesc, Template, TemplateError};
6use crate::analyzer::kubelint::types::{Diagnostic, ObjectKindsDesc};
7
8/// Template for detecting deployments without rolling update strategy.
9pub struct RollingUpdateStrategyTemplate;
10
11impl Template for RollingUpdateStrategyTemplate {
12    fn key(&self) -> &str {
13        "rolling-update-strategy"
14    }
15
16    fn human_name(&self) -> &str {
17        "Rolling Update Strategy"
18    }
19
20    fn description(&self) -> &str {
21        "Detects deployments without a rolling update strategy configured"
22    }
23
24    fn supported_object_kinds(&self) -> ObjectKindsDesc {
25        ObjectKindsDesc::new(&["Deployment", "DaemonSet"])
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(RollingUpdateStrategyCheck))
37    }
38}
39
40struct RollingUpdateStrategyCheck;
41
42impl CheckFunc for RollingUpdateStrategyCheck {
43    fn check(&self, object: &Object) -> Vec<Diagnostic> {
44        let mut diagnostics = Vec::new();
45
46        match &object.k8s_object {
47            K8sObject::Deployment(dep) => {
48                let strategy = dep.strategy.as_ref();
49                let strategy_type = strategy.and_then(|s| s.type_.as_deref());
50
51                // Check if strategy is not RollingUpdate (or unset - defaults to RollingUpdate)
52                if strategy_type == Some("Recreate") {
53                    diagnostics.push(Diagnostic {
54                        message: format!(
55                            "Deployment '{}' uses Recreate strategy instead of RollingUpdate",
56                            object.name()
57                        ),
58                        remediation: Some(
59                            "Consider using RollingUpdate strategy for zero-downtime deployments."
60                                .to_string(),
61                        ),
62                    });
63                }
64
65                // Check if RollingUpdate but no parameters configured
66                if strategy_type.is_none() || strategy_type == Some("RollingUpdate") {
67                    let rolling_update = strategy.and_then(|s| s.rolling_update.as_ref());
68                    if rolling_update.is_none() {
69                        diagnostics.push(Diagnostic {
70                            message: format!(
71                                "Deployment '{}' has no explicit rolling update configuration",
72                                object.name()
73                            ),
74                            remediation: Some(
75                                "Configure strategy.rollingUpdate.maxSurge and maxUnavailable \
76                                 for controlled rollouts."
77                                    .to_string(),
78                            ),
79                        });
80                    }
81                }
82            }
83            K8sObject::DaemonSet(ds) => {
84                let strategy_type = ds.update_strategy.as_ref().and_then(|s| s.type_.as_deref());
85
86                if strategy_type == Some("OnDelete") {
87                    diagnostics.push(Diagnostic {
88                        message: format!(
89                            "DaemonSet '{}' uses OnDelete strategy instead of RollingUpdate",
90                            object.name()
91                        ),
92                        remediation: Some(
93                            "Consider using RollingUpdate strategy for automatic updates."
94                                .to_string(),
95                        ),
96                    });
97                }
98            }
99            _ => {}
100        }
101
102        diagnostics
103    }
104}