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::config_from;
42    use serde_json::json;
43
44    use super::*;
45
46    async fn autoscaling_config_from(value: serde_json::Value) -> AutoscalingFailoverConfiguration {
47        AutoscalingFailoverConfiguration::from_configuration(&config_from(value).await)
48            .expect("autoscaling failover configuration should deserialize")
49    }
50
51    #[tokio::test]
52    async fn defaults_to_disabled_with_default_metric_allowlist() {
53        let config = autoscaling_config_from(json!({})).await;
54
55        assert!(!config.is_branch_requested());
56        assert_eq!(
57            config.metrics(),
58            ["container.memory.usage".to_string(), "container.cpu.usage".to_string()]
59        );
60    }
61
62    #[tokio::test]
63    async fn branch_is_requested_when_enabled_with_non_empty_metrics() {
64        let config = autoscaling_config_from(json!({
65            "autoscaling": {
66                "failover": {
67                    "enabled": true,
68                    "metrics": ["custom.metric"]
69                }
70            }
71        }))
72        .await;
73
74        assert!(config.is_branch_requested());
75        assert_eq!(config.metrics(), ["custom.metric".to_string()]);
76    }
77
78    #[tokio::test]
79    async fn empty_metric_allowlist_disables_branch() {
80        let config = autoscaling_config_from(json!({
81            "autoscaling": {
82                "failover": {
83                    "enabled": true,
84                    "metrics": []
85                }
86            }
87        }))
88        .await;
89
90        assert!(!config.is_branch_requested());
91        assert!(config.metrics().is_empty());
92    }
93}