Skip to main content

saluki_components/config/
autoscaling_failover.rs

1//! Autoscaling failover configuration.
2
3use saluki_config::GenericConfiguration;
4use saluki_error::GenericError;
5
6fn default_metrics() -> Vec<String> {
7    vec!["container.memory.usage".to_string(), "container.cpu.usage".to_string()]
8}
9
10/// Autoscaling failover configuration for the metrics pipeline.
11#[derive(Clone, Debug, Eq, PartialEq)]
12pub struct AutoscalingFailoverConfiguration {
13    enabled: bool,
14    metrics: Vec<String>,
15}
16
17impl AutoscalingFailoverConfiguration {
18    /// Creates a new `AutoscalingFailoverConfiguration` from the given configuration.
19    pub fn from_configuration(config: &GenericConfiguration) -> Result<Self, GenericError> {
20        Ok(Self {
21            enabled: config.try_get_typed("autoscaling.failover.enabled")?.unwrap_or(false),
22            metrics: config
23                .try_get_typed("autoscaling.failover.metrics")?
24                .unwrap_or_else(default_metrics),
25        })
26    }
27
28    /// Returns whether the autoscaling failover branch is requested by configuration.
29    pub fn is_branch_requested(&self) -> bool {
30        self.enabled && !self.metrics.is_empty()
31    }
32
33    /// Returns the metric name allowlist.
34    pub fn metrics(&self) -> &[String] {
35        &self.metrics
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use saluki_config::ConfigurationLoader;
42    use serde_json::json;
43
44    use super::*;
45
46    async fn autoscaling_config_from(value: serde_json::Value) -> AutoscalingFailoverConfiguration {
47        let (config, _) = ConfigurationLoader::for_tests(Some(value), None, false).await;
48        AutoscalingFailoverConfiguration::from_configuration(&config)
49            .expect("autoscaling failover configuration should deserialize")
50    }
51
52    #[tokio::test]
53    async fn defaults_to_disabled_with_default_metric_allowlist() {
54        let config = autoscaling_config_from(json!({})).await;
55
56        assert!(!config.is_branch_requested());
57        assert_eq!(
58            config.metrics(),
59            ["container.memory.usage".to_string(), "container.cpu.usage".to_string()]
60        );
61    }
62
63    #[tokio::test]
64    async fn branch_is_requested_when_enabled_with_non_empty_metrics() {
65        let config = autoscaling_config_from(json!({
66            "autoscaling": {
67                "failover": {
68                    "enabled": true,
69                    "metrics": ["custom.metric"]
70                }
71            }
72        }))
73        .await;
74
75        assert!(config.is_branch_requested());
76        assert_eq!(config.metrics(), ["custom.metric".to_string()]);
77    }
78
79    #[tokio::test]
80    async fn empty_metric_allowlist_disables_branch() {
81        let config = autoscaling_config_from(json!({
82            "autoscaling": {
83                "failover": {
84                    "enabled": true,
85                    "metrics": []
86                }
87            }
88        }))
89        .await;
90
91        assert!(!config.is_branch_requested());
92        assert!(config.metrics().is_empty());
93    }
94}