Skip to content

Commit 52d915d

Browse files
authored
Merge pull request #19 from RobGeada/ExpandConfig
Feat: Default orch config, broader detector options
2 parents f9783b4 + a7b9a3e commit 52d915d

File tree

2 files changed

+159
-6
lines changed

2 files changed

+159
-6
lines changed

src/config.rs

Lines changed: 156 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
use std::collections::HashSet;
12
use std::fs;
23

34
use serde::Deserialize;
45

56
#[derive(Debug, Deserialize, Clone)]
67
pub struct GatewayConfig {
8+
#[serde(default)]
79
pub orchestrator: OrchestratorConfig,
810
pub detectors: Vec<DetectorConfig>,
911
pub routes: Vec<RouteConfig>,
@@ -15,25 +17,48 @@ pub struct OrchestratorConfig {
1517
pub port: Option<u16>,
1618
}
1719

20+
impl Default for OrchestratorConfig {
21+
fn default() -> Self {
22+
OrchestratorConfig {
23+
host: "localhost".to_string(),
24+
port: Some(8032),
25+
}
26+
}
27+
}
28+
1829
#[derive(Debug, Deserialize, Clone)]
1930
pub struct DetectorConfig {
2031
pub name: String,
32+
#[serde(default)]
33+
pub server: Option<String>,
2134
pub input: bool,
2235
pub output: bool,
2336
pub detector_params: Option<serde_json::Value>,
2437
}
2538

39+
impl DetectorConfig {
40+
pub fn with_server_default(mut self) -> Self {
41+
if self.server.is_none() {
42+
self.server = Some(self.name.clone());
43+
}
44+
self
45+
}
46+
}
47+
2648
#[derive(Debug, Deserialize, Clone)]
2749
pub struct RouteConfig {
2850
pub name: String,
2951
pub detectors: Vec<String>,
3052
pub fallback_message: Option<String>,
3153
}
3254

55+
3356
pub fn read_config(path: &str) -> GatewayConfig {
3457
let result = fs::read_to_string(path).expect(&format!("could not read file: {}", path));
3558

36-
serde_yml::from_str(&result).expect("failed to read in yaml config")
59+
let mut cfg: GatewayConfig = serde_yml::from_str(&result).expect("failed to read in yaml config");
60+
cfg.detectors = cfg.detectors.into_iter().map(|d| d.with_server_default()).collect();
61+
cfg
3762
}
3863

3964
pub fn validate_registered_detectors(gateway_cfg: &GatewayConfig) {
@@ -43,15 +68,43 @@ pub fn validate_registered_detectors(gateway_cfg: &GatewayConfig) {
4368
.map(|detector| &detector.name)
4469
.collect();
4570

71+
let mut issues = Vec::new();
4672
for route in gateway_cfg.routes.iter() {
4773
for detector in &route.detectors {
4874
if !detector_names.contains(&detector) {
49-
panic!(
50-
"could not find detector {} in route {}",
75+
issues.push(format!(
76+
"- could not find detector '{}' in route '{}'",
5177
detector, route.name
52-
);
78+
));
5379
}
5480
}
81+
82+
// Validate no duplicate input/output servers
83+
let mut seen_input = HashSet::new();
84+
let mut seen_output = HashSet::new();
85+
86+
for detector_name in &route.detectors {
87+
if let Some(detector_cfg) = gateway_cfg.detectors.iter().find(|d| &d.name == detector_name) {
88+
if detector_cfg.input {
89+
let server = detector_cfg.server.as_ref().unwrap();
90+
if !seen_input.insert(server) {
91+
issues.push(format!(
92+
"- route '{}' contains more than one input detector with server '{}'",
93+
route.name, server
94+
));
95+
}
96+
if !seen_output.insert(server) {
97+
issues.push(format!(
98+
"- route '{}' contains more than one output detector with server '{}'",
99+
route.name, server
100+
));
101+
}
102+
}
103+
}
104+
}
105+
}
106+
if !issues.is_empty() {
107+
panic!("Config validation failed:\n{}", issues.join("\n"));
55108
}
56109
}
57110

@@ -69,6 +122,7 @@ mod tests {
69122
},
70123
detectors: vec![DetectorConfig {
71124
name: "regex".to_string(),
125+
server: None,
72126
input: false,
73127
output: false,
74128
detector_params: None,
@@ -82,4 +136,102 @@ mod tests {
82136

83137
validate_registered_detectors(&gc);
84138
}
139+
140+
#[test]
141+
#[should_panic]
142+
fn test_validate_multiple_same_server_input_detectors() {
143+
let gc = GatewayConfig {
144+
orchestrator: OrchestratorConfig {
145+
host: "localhost".to_string(),
146+
port: Some(1234),
147+
},
148+
detectors: vec![DetectorConfig {
149+
name: "regex-1".to_string(),
150+
server: Some("server-a".to_string()),
151+
input: true,
152+
output: false,
153+
detector_params: None,
154+
}, DetectorConfig {
155+
name: "regex-2".to_string(),
156+
server: Some("server-a".to_string()),
157+
input: true,
158+
output: false,
159+
detector_params: None,
160+
},
161+
162+
],
163+
routes: vec![RouteConfig {
164+
name: "route1".to_string(),
165+
detectors: vec!["regex-1".to_string(), "regex-2".to_string()],
166+
fallback_message: None,
167+
}],
168+
};
169+
170+
validate_registered_detectors(&gc);
171+
}
172+
173+
#[test]
174+
#[should_panic]
175+
fn test_validate_multiple_same_server_output_detectors() {
176+
let gc = GatewayConfig {
177+
orchestrator: OrchestratorConfig {
178+
host: "localhost".to_string(),
179+
port: Some(1234),
180+
},
181+
detectors: vec![DetectorConfig {
182+
name: "regex-1".to_string(),
183+
server: Some("server-a".to_string()),
184+
input: false,
185+
output: true,
186+
detector_params: None,
187+
}, DetectorConfig {
188+
name: "regex-2".to_string(),
189+
server: Some("server-a".to_string()),
190+
input: false,
191+
output: true,
192+
detector_params: None,
193+
},
194+
195+
],
196+
routes: vec![RouteConfig {
197+
name: "route1".to_string(),
198+
detectors: vec!["regex-1".to_string(), "regex-2".to_string()],
199+
fallback_message: None,
200+
}],
201+
};
202+
203+
validate_registered_detectors(&gc);
204+
}
205+
206+
#[test]
207+
fn test_validate_multiple_same_server_detectors() {
208+
let gc = GatewayConfig {
209+
orchestrator: OrchestratorConfig {
210+
host: "localhost".to_string(),
211+
port: Some(1234),
212+
},
213+
detectors: vec![DetectorConfig {
214+
name: "regex-1".to_string(),
215+
server: Some("server-a".to_string()),
216+
input: true,
217+
output: false,
218+
detector_params: None,
219+
}, DetectorConfig {
220+
name: "regex-2".to_string(),
221+
server: Some("server-a".to_string()),
222+
input: false,
223+
output: true,
224+
detector_params: None,
225+
},
226+
227+
],
228+
routes: vec![RouteConfig {
229+
name: "route1".to_string(),
230+
detectors: vec!["regex-1".to_string(), "regex-2".to_string()],
231+
fallback_message: None,
232+
}],
233+
};
234+
235+
validate_registered_detectors(&gc);
236+
}
85237
}

src/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ fn get_orchestrator_detectors(
3030
for detector in detector_config {
3131
if detectors.contains(&detector.name) && detector.detector_params.is_some() {
3232
let detector_params = detector.detector_params.unwrap();
33+
let key = detector.server.clone().unwrap_or_else(|| detector.name.clone());
3334
if detector.input {
34-
input_detectors.insert(detector.name.clone(), detector_params.clone());
35+
input_detectors.insert(key.clone(), detector_params.clone());
3536
}
3637
if detector.output {
37-
output_detectors.insert(detector.name, detector_params);
38+
output_detectors.insert(key, detector_params);
3839
}
3940
}
4041
}

0 commit comments

Comments
 (0)