rustfs_targets/runtime/
sidecar_protocol.rs1use crate::TargetDomain;
16use serde::{Deserialize, Serialize};
17
18pub const SIDECAR_RUNTIME_PROTOCOL_VERSION: &str = "rustfs.target-runtime.v1";
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
21#[serde(rename_all = "snake_case")]
22pub enum SidecarPluginCapability {
23 HealthCheck,
24 SendEvent,
25 Shutdown,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
29#[serde(rename_all = "snake_case")]
30pub struct SidecarHandshake {
31 pub protocol_version: String,
32 pub plugin_id: String,
33 pub plugin_version: String,
34 pub supported_domains: Vec<TargetDomain>,
35 pub capabilities: Vec<SidecarPluginCapability>,
36}
37
38impl SidecarHandshake {
39 pub fn validate(&self, expected_plugin_id: &str) -> Result<(), String> {
40 if self.protocol_version != SIDECAR_RUNTIME_PROTOCOL_VERSION {
41 return Err(format!(
42 "unsupported sidecar protocol version: expected {}, got {}",
43 SIDECAR_RUNTIME_PROTOCOL_VERSION, self.protocol_version
44 ));
45 }
46
47 if self.plugin_id != expected_plugin_id {
48 return Err(format!(
49 "sidecar plugin id mismatch: expected {}, got {}",
50 expected_plugin_id, self.plugin_id
51 ));
52 }
53
54 for capability in [
55 SidecarPluginCapability::HealthCheck,
56 SidecarPluginCapability::SendEvent,
57 SidecarPluginCapability::Shutdown,
58 ] {
59 if !self.capabilities.contains(&capability) {
60 return Err(format!("sidecar handshake missing required capability: {:?}", capability));
61 }
62 }
63
64 Ok(())
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::{SIDECAR_RUNTIME_PROTOCOL_VERSION, SidecarHandshake, SidecarPluginCapability};
71 use crate::TargetDomain;
72
73 #[test]
74 fn sidecar_handshake_accepts_expected_contract() {
75 let handshake = SidecarHandshake {
76 protocol_version: SIDECAR_RUNTIME_PROTOCOL_VERSION.to_string(),
77 plugin_id: "external:webhook".to_string(),
78 plugin_version: "1.2.3".to_string(),
79 supported_domains: vec![TargetDomain::Notify],
80 capabilities: vec![
81 SidecarPluginCapability::HealthCheck,
82 SidecarPluginCapability::SendEvent,
83 SidecarPluginCapability::Shutdown,
84 ],
85 };
86
87 assert!(handshake.validate("external:webhook").is_ok());
88 }
89
90 #[test]
91 fn sidecar_handshake_rejects_protocol_mismatch() {
92 let handshake = SidecarHandshake {
93 protocol_version: "rustfs.target-runtime.v0".to_string(),
94 plugin_id: "external:webhook".to_string(),
95 plugin_version: "1.2.3".to_string(),
96 supported_domains: vec![TargetDomain::Notify],
97 capabilities: vec![
98 SidecarPluginCapability::HealthCheck,
99 SidecarPluginCapability::SendEvent,
100 SidecarPluginCapability::Shutdown,
101 ],
102 };
103
104 assert!(handshake.validate("external:webhook").is_err());
105 }
106}