use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, utoipa::ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum OverlayMode {
#[default]
Auto,
Shared,
Dedicated,
}
impl OverlayMode {
#[must_use]
pub fn resolve(self) -> OverlayMode {
match self {
OverlayMode::Auto | OverlayMode::Shared => OverlayMode::Shared,
OverlayMode::Dedicated => OverlayMode::Dedicated,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OverlayConfig {
#[serde(default)]
pub mode: OverlayMode,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
}
impl OverlayConfig {
#[must_use]
pub fn resolved_parent_v0_51(&self) -> Option<&str> {
match self.parent.as_deref() {
None | Some("cluster") => None,
Some(other) => {
tracing::warn!(
parent = other,
"OverlayConfig.parent only supports `cluster` (or unset) in v0.51; \
service-of-service nesting is reserved for a future round. \
Falling back to cluster parent.",
);
None
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn overlay_mode_default_is_auto() {
assert_eq!(OverlayMode::default(), OverlayMode::Auto);
}
#[test]
fn overlay_mode_resolve() {
assert_eq!(OverlayMode::Auto.resolve(), OverlayMode::Shared);
assert_eq!(OverlayMode::Shared.resolve(), OverlayMode::Shared);
assert_eq!(OverlayMode::Dedicated.resolve(), OverlayMode::Dedicated);
}
#[test]
fn overlay_mode_serde_lowercase() {
assert_eq!(
serde_json::to_string(&OverlayMode::Auto).unwrap(),
"\"auto\""
);
assert_eq!(
serde_json::to_string(&OverlayMode::Shared).unwrap(),
"\"shared\""
);
assert_eq!(
serde_json::to_string(&OverlayMode::Dedicated).unwrap(),
"\"dedicated\""
);
assert_eq!(
serde_json::from_str::<OverlayMode>("\"shared\"").unwrap(),
OverlayMode::Shared,
);
}
#[test]
fn overlay_config_default_is_auto_no_parent() {
let cfg = OverlayConfig::default();
assert_eq!(cfg.mode, OverlayMode::Auto);
assert_eq!(cfg.parent, None);
assert_eq!(cfg.resolved_parent_v0_51(), None);
}
#[test]
fn overlay_config_cluster_parent_is_none() {
let cfg = OverlayConfig {
mode: OverlayMode::Shared,
parent: Some("cluster".to_string()),
};
assert_eq!(cfg.resolved_parent_v0_51(), None);
}
#[test]
fn overlay_config_other_parent_warns_and_returns_none() {
let cfg = OverlayConfig {
mode: OverlayMode::Shared,
parent: Some("svc-other".to_string()),
};
assert_eq!(cfg.resolved_parent_v0_51(), None);
}
}