1use camel_core::TracerConfig;
2use config::{Config, ConfigError};
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::env;
6use std::time::Duration;
7
8#[derive(Debug, Clone, Deserialize)]
9pub struct CamelConfig {
10 #[serde(default)]
11 pub routes: Vec<String>,
12
13 #[serde(default)]
16 pub watch: bool,
17
18 #[serde(default)]
22 pub runtime_journal_path: Option<String>,
23
24 #[serde(default = "default_log_level")]
25 pub log_level: String,
26
27 #[serde(default = "default_timeout_ms")]
28 pub timeout_ms: u64,
29
30 #[serde(default)]
31 pub components: ComponentsConfig,
32
33 #[serde(default)]
34 pub observability: ObservabilityConfig,
35
36 #[serde(default)]
37 pub supervision: Option<SupervisionCamelConfig>,
38}
39
40#[derive(Debug, Clone, Deserialize, Default, PartialEq)]
41pub struct ComponentsConfig {
42 #[serde(default)]
43 pub timer: Option<TimerConfig>,
44
45 #[serde(default)]
46 pub http: Option<HttpCamelConfig>,
47
48 #[serde(default)]
49 pub kafka: Option<KafkaCamelConfig>,
50
51 #[serde(default)]
52 pub redis: Option<RedisCamelConfig>,
53
54 #[serde(default)]
55 pub sql: Option<SqlCamelConfig>,
56
57 #[serde(default)]
58 pub file: Option<FileCamelConfig>,
59
60 #[serde(default)]
61 pub container: Option<ContainerCamelConfig>,
62}
63
64#[derive(Debug, Clone, Deserialize, PartialEq)]
65pub struct TimerConfig {
66 #[serde(default = "default_timer_period")]
67 pub period: u64,
68}
69
70#[derive(Debug, Clone, Deserialize, PartialEq)]
71pub struct HttpCamelConfig {
72 #[serde(default = "default_http_connect_timeout_ms")]
73 pub connect_timeout_ms: u64,
74
75 #[serde(default = "default_http_response_timeout_ms")]
76 pub response_timeout_ms: u64,
77
78 #[serde(default = "default_http_max_connections")]
79 pub max_connections: usize,
80
81 #[serde(default = "default_http_max_body_size")]
82 pub max_body_size: usize,
83
84 #[serde(default = "default_http_max_request_body")]
85 pub max_request_body: usize,
86
87 #[serde(default)]
88 pub allow_private_ips: bool,
89}
90
91impl Default for HttpCamelConfig {
92 fn default() -> Self {
93 Self {
94 connect_timeout_ms: default_http_connect_timeout_ms(),
95 response_timeout_ms: default_http_response_timeout_ms(),
96 max_connections: default_http_max_connections(),
97 max_body_size: default_http_max_body_size(),
98 max_request_body: default_http_max_request_body(),
99 allow_private_ips: false,
100 }
101 }
102}
103
104#[derive(Debug, Clone, Deserialize, PartialEq)]
105pub struct KafkaCamelConfig {
106 #[serde(default = "default_kafka_brokers")]
107 pub brokers: String,
108 #[serde(default = "default_kafka_group_id")]
109 pub group_id: String,
110 #[serde(default = "default_kafka_session_timeout_ms")]
111 pub session_timeout_ms: u32,
112 #[serde(default = "default_kafka_request_timeout_ms")]
113 pub request_timeout_ms: u32,
114 #[serde(default = "default_kafka_auto_offset_reset")]
115 pub auto_offset_reset: String,
116 #[serde(default = "default_kafka_security_protocol")]
117 pub security_protocol: String,
118}
119
120impl Default for KafkaCamelConfig {
121 fn default() -> Self {
122 Self {
123 brokers: default_kafka_brokers(),
124 group_id: default_kafka_group_id(),
125 session_timeout_ms: default_kafka_session_timeout_ms(),
126 request_timeout_ms: default_kafka_request_timeout_ms(),
127 auto_offset_reset: default_kafka_auto_offset_reset(),
128 security_protocol: default_kafka_security_protocol(),
129 }
130 }
131}
132
133#[derive(Debug, Clone, Deserialize, PartialEq)]
134pub struct RedisCamelConfig {
135 #[serde(default = "default_redis_host")]
136 pub host: String,
137 #[serde(default = "default_redis_port")]
138 pub port: u16,
139}
140
141impl Default for RedisCamelConfig {
142 fn default() -> Self {
143 Self {
144 host: default_redis_host(),
145 port: default_redis_port(),
146 }
147 }
148}
149
150#[derive(Debug, Clone, Deserialize, PartialEq)]
151pub struct SqlCamelConfig {
152 #[serde(default = "default_sql_max_connections")]
153 pub max_connections: u32,
154 #[serde(default = "default_sql_min_connections")]
155 pub min_connections: u32,
156 #[serde(default = "default_sql_idle_timeout_secs")]
157 pub idle_timeout_secs: u64,
158 #[serde(default = "default_sql_max_lifetime_secs")]
159 pub max_lifetime_secs: u64,
160}
161
162impl Default for SqlCamelConfig {
163 fn default() -> Self {
164 Self {
165 max_connections: default_sql_max_connections(),
166 min_connections: default_sql_min_connections(),
167 idle_timeout_secs: default_sql_idle_timeout_secs(),
168 max_lifetime_secs: default_sql_max_lifetime_secs(),
169 }
170 }
171}
172
173#[derive(Debug, Clone, Deserialize, PartialEq)]
174pub struct FileCamelConfig {
175 #[serde(default = "default_file_delay_ms")]
176 pub delay_ms: u64,
177 #[serde(default = "default_file_initial_delay_ms")]
178 pub initial_delay_ms: u64,
179 #[serde(default = "default_file_read_timeout_ms")]
180 pub read_timeout_ms: u64,
181 #[serde(default = "default_file_write_timeout_ms")]
182 pub write_timeout_ms: u64,
183}
184
185impl Default for FileCamelConfig {
186 fn default() -> Self {
187 Self {
188 delay_ms: default_file_delay_ms(),
189 initial_delay_ms: default_file_initial_delay_ms(),
190 read_timeout_ms: default_file_read_timeout_ms(),
191 write_timeout_ms: default_file_write_timeout_ms(),
192 }
193 }
194}
195
196#[derive(Debug, Clone, Deserialize, PartialEq)]
197pub struct ContainerCamelConfig {
198 #[serde(default = "default_container_docker_host")]
199 pub docker_host: String,
200}
201
202impl Default for ContainerCamelConfig {
203 fn default() -> Self {
204 Self {
205 docker_host: default_container_docker_host(),
206 }
207 }
208}
209
210#[derive(Debug, Clone, Deserialize, PartialEq)]
211pub struct PrometheusCamelConfig {
212 #[serde(default)]
213 pub enabled: bool,
214 #[serde(default = "default_prometheus_host")]
215 pub host: String,
216 #[serde(default = "default_prometheus_port")]
217 pub port: u16,
218}
219
220impl Default for PrometheusCamelConfig {
221 fn default() -> Self {
222 Self {
223 enabled: false,
224 host: default_prometheus_host(),
225 port: default_prometheus_port(),
226 }
227 }
228}
229
230fn default_prometheus_host() -> String {
231 "0.0.0.0".to_string()
232}
233fn default_prometheus_port() -> u16 {
234 9090
235}
236
237#[derive(Debug, Clone, Deserialize, Default)]
238pub struct ObservabilityConfig {
239 #[serde(default)]
240 pub tracer: TracerConfig,
241
242 #[serde(default)]
243 pub otel: Option<OtelCamelConfig>,
244
245 #[serde(default)]
246 pub prometheus: Option<PrometheusCamelConfig>,
247}
248
249#[derive(Debug, Clone, Deserialize, Default, PartialEq)]
251#[serde(rename_all = "snake_case")]
252pub enum OtelProtocol {
253 #[default]
254 Grpc,
255 Http,
256}
257
258#[derive(Debug, Clone, Deserialize, Default, PartialEq)]
260#[serde(rename_all = "snake_case")]
261pub enum OtelSampler {
262 #[default]
263 AlwaysOn,
264 AlwaysOff,
265 Ratio,
266}
267
268#[derive(Debug, Clone, Deserialize, Default)]
270pub struct OtelCamelConfig {
271 #[serde(default)]
272 pub enabled: bool,
273
274 #[serde(default = "default_otel_endpoint")]
275 pub endpoint: String,
276
277 #[serde(default = "default_otel_service_name")]
278 pub service_name: String,
279
280 #[serde(default = "default_otel_log_level")]
281 pub log_level: String,
282
283 #[serde(default)]
284 pub protocol: OtelProtocol,
285
286 #[serde(default)]
287 pub sampler: OtelSampler,
288
289 #[serde(default)]
290 pub sampler_ratio: Option<f64>,
291
292 #[serde(default = "default_otel_metrics_interval_ms")]
293 pub metrics_interval_ms: u64,
294
295 #[serde(default = "default_true")]
296 pub logs_enabled: bool,
297
298 #[serde(default)]
299 pub resource_attrs: HashMap<String, String>,
300}
301
302#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
303pub struct SupervisionCamelConfig {
304 pub max_attempts: Option<u32>,
306
307 #[serde(default = "default_initial_delay_ms")]
309 pub initial_delay_ms: u64,
310
311 #[serde(default = "default_backoff_multiplier")]
313 pub backoff_multiplier: f64,
314
315 #[serde(default = "default_max_delay_ms")]
317 pub max_delay_ms: u64,
318}
319
320impl Default for SupervisionCamelConfig {
321 fn default() -> Self {
322 Self {
323 max_attempts: Some(5),
324 initial_delay_ms: 1000,
325 backoff_multiplier: 2.0,
326 max_delay_ms: 60000,
327 }
328 }
329}
330
331impl SupervisionCamelConfig {
332 pub fn into_supervision_config(self) -> camel_api::SupervisionConfig {
334 camel_api::SupervisionConfig {
335 max_attempts: self.max_attempts,
336 initial_delay: Duration::from_millis(self.initial_delay_ms),
337 backoff_multiplier: self.backoff_multiplier,
338 max_delay: Duration::from_millis(self.max_delay_ms),
339 }
340 }
341}
342
343fn default_log_level() -> String {
344 "INFO".to_string()
345}
346fn default_timeout_ms() -> u64 {
347 5000
348}
349fn default_timer_period() -> u64 {
350 1000
351}
352fn default_http_connect_timeout_ms() -> u64 {
353 5_000
354}
355fn default_http_response_timeout_ms() -> u64 {
356 30_000
357}
358fn default_http_max_connections() -> usize {
359 100
360}
361fn default_http_max_body_size() -> usize {
362 10_485_760
363}
364fn default_http_max_request_body() -> usize {
365 2_097_152
366}
367
368fn default_kafka_brokers() -> String {
369 "localhost:9092".to_string()
370}
371fn default_kafka_group_id() -> String {
372 "camel".to_string()
373}
374fn default_kafka_session_timeout_ms() -> u32 {
375 45_000
376}
377fn default_kafka_request_timeout_ms() -> u32 {
378 30_000
379}
380fn default_kafka_auto_offset_reset() -> String {
381 "latest".to_string()
382}
383fn default_kafka_security_protocol() -> String {
384 "plaintext".to_string()
385}
386
387fn default_redis_host() -> String {
388 "localhost".to_string()
389}
390fn default_redis_port() -> u16 {
391 6379
392}
393
394fn default_sql_max_connections() -> u32 {
395 5
396}
397fn default_sql_min_connections() -> u32 {
398 1
399}
400fn default_sql_idle_timeout_secs() -> u64 {
401 300
402}
403fn default_sql_max_lifetime_secs() -> u64 {
404 1_800
405}
406
407fn default_file_delay_ms() -> u64 {
408 500
409}
410fn default_file_initial_delay_ms() -> u64 {
411 1_000
412}
413fn default_file_read_timeout_ms() -> u64 {
414 30_000
415}
416fn default_file_write_timeout_ms() -> u64 {
417 30_000
418}
419
420fn default_container_docker_host() -> String {
421 "unix:///var/run/docker.sock".to_string()
422}
423
424fn default_otel_endpoint() -> String {
425 "http://localhost:4317".to_string()
426}
427fn default_otel_service_name() -> String {
428 "rust-camel".to_string()
429}
430fn default_otel_log_level() -> String {
431 "info".to_string()
432}
433fn default_otel_metrics_interval_ms() -> u64 {
434 60000
435}
436fn default_true() -> bool {
437 true
438}
439
440fn default_initial_delay_ms() -> u64 {
441 1000
442}
443
444fn default_backoff_multiplier() -> f64 {
445 2.0
446}
447
448fn default_max_delay_ms() -> u64 {
449 60000
450}
451
452fn merge_toml_values(base: &mut toml::Value, overlay: &toml::Value) {
455 match (base, overlay) {
456 (toml::Value::Table(base_table), toml::Value::Table(overlay_table)) => {
457 for (key, value) in overlay_table {
458 if let Some(base_value) = base_table.get_mut(key) {
459 merge_toml_values(base_value, value);
461 } else {
462 base_table.insert(key.clone(), value.clone());
464 }
465 }
466 }
467 (base, overlay) => {
469 *base = overlay.clone();
470 }
471 }
472}
473
474impl CamelConfig {
475 pub fn from_file(path: &str) -> Result<Self, ConfigError> {
476 Self::from_file_with_profile(path, None)
477 }
478
479 pub fn from_file_with_env(path: &str) -> Result<Self, ConfigError> {
480 Self::from_file_with_profile_and_env(path, None)
481 }
482
483 pub fn from_file_with_profile(path: &str, profile: Option<&str>) -> Result<Self, ConfigError> {
484 let env_profile = env::var("CAMEL_PROFILE").ok();
486 let profile = profile.or(env_profile.as_deref());
487
488 let content = std::fs::read_to_string(path)
490 .map_err(|e| ConfigError::Message(format!("Failed to read config file: {}", e)))?;
491 let mut config_value: toml::Value = toml::from_str(&content)
492 .map_err(|e| ConfigError::Message(format!("Failed to parse TOML: {}", e)))?;
493
494 if let Some(p) = profile {
496 let default_value = config_value.get("default").cloned();
498
499 let profile_value = config_value.get(p).cloned();
501
502 if let (Some(mut base), Some(overlay)) = (default_value, profile_value) {
503 merge_toml_values(&mut base, &overlay);
505
506 config_value = base;
508 } else if let Some(profile_val) = config_value.get(p).cloned() {
509 config_value = profile_val;
511 } else {
512 return Err(ConfigError::Message(format!("Unknown profile: {}", p)));
513 }
514 } else {
515 if let Some(default_val) = config_value.get("default").cloned() {
517 config_value = default_val;
518 }
519 }
520
521 let merged_toml = toml::to_string(&config_value).map_err(|e| {
523 ConfigError::Message(format!("Failed to serialize merged config: {}", e))
524 })?;
525
526 let config = Config::builder()
527 .add_source(config::File::from_str(
528 &merged_toml,
529 config::FileFormat::Toml,
530 ))
531 .build()?;
532
533 config.try_deserialize()
534 }
535
536 pub fn from_file_with_profile_and_env(
537 path: &str,
538 profile: Option<&str>,
539 ) -> Result<Self, ConfigError> {
540 let env_profile = env::var("CAMEL_PROFILE").ok();
542 let profile = profile.or(env_profile.as_deref());
543
544 let content = std::fs::read_to_string(path)
546 .map_err(|e| ConfigError::Message(format!("Failed to read config file: {}", e)))?;
547 let mut config_value: toml::Value = toml::from_str(&content)
548 .map_err(|e| ConfigError::Message(format!("Failed to parse TOML: {}", e)))?;
549
550 if let Some(p) = profile {
552 let default_value = config_value.get("default").cloned();
554
555 let profile_value = config_value.get(p).cloned();
557
558 if let (Some(mut base), Some(overlay)) = (default_value, profile_value) {
559 merge_toml_values(&mut base, &overlay);
561
562 config_value = base;
564 } else if let Some(profile_val) = config_value.get(p).cloned() {
565 config_value = profile_val;
567 } else {
568 return Err(ConfigError::Message(format!("Unknown profile: {}", p)));
569 }
570 } else {
571 if let Some(default_val) = config_value.get("default").cloned() {
573 config_value = default_val;
574 }
575 }
576
577 let merged_toml = toml::to_string(&config_value).map_err(|e| {
579 ConfigError::Message(format!("Failed to serialize merged config: {}", e))
580 })?;
581
582 let config = Config::builder()
583 .add_source(config::File::from_str(
584 &merged_toml,
585 config::FileFormat::Toml,
586 ))
587 .add_source(config::Environment::with_prefix("CAMEL").try_parsing(true))
588 .build()?;
589
590 config.try_deserialize()
591 }
592
593 pub fn from_env_or_default() -> Result<Self, ConfigError> {
594 let path = env::var("CAMEL_CONFIG_FILE").unwrap_or_else(|_| "Camel.toml".to_string());
595
596 Self::from_file(&path)
597 }
598}
599
600#[cfg(test)]
601mod http_camel_config_tests {
602 use super::*;
603
604 fn parse(toml: &str) -> CamelConfig {
605 let cfg = config::Config::builder()
606 .add_source(config::File::from_str(toml, config::FileFormat::Toml))
607 .build()
608 .unwrap();
609 cfg.try_deserialize().unwrap()
610 }
611
612 #[test]
613 fn test_http_camel_config_defaults() {
614 let cfg = parse("");
615 assert!(cfg.components.http.is_none());
616 }
617
618 #[test]
619 fn test_http_camel_config_default_matches_serde() {
620 let default = HttpCamelConfig::default();
621 assert_eq!(default.connect_timeout_ms, 5_000);
622 assert_eq!(default.response_timeout_ms, 30_000);
623 assert_eq!(default.max_connections, 100);
624 assert_eq!(default.max_body_size, 10_485_760);
625 assert_eq!(default.max_request_body, 2_097_152);
626 assert!(!default.allow_private_ips);
627 }
628
629 #[test]
630 fn test_http_camel_config_partial_override() {
631 let cfg = parse(
632 r#"
633[components.http]
634connect_timeout_ms = 1000
635"#,
636 );
637 let http = cfg.components.http.unwrap();
638 assert_eq!(http.connect_timeout_ms, 1000);
639 assert_eq!(http.response_timeout_ms, 30_000);
640 assert_eq!(http.max_connections, 100);
641 assert_eq!(http.max_body_size, 10_485_760);
642 assert_eq!(http.max_request_body, 2_097_152);
643 assert!(!http.allow_private_ips);
644 }
645
646 #[test]
647 fn test_http_camel_config_all_fields() {
648 let cfg = parse(
649 r#"
650[components.http]
651connect_timeout_ms = 2000
652response_timeout_ms = 60000
653max_connections = 50
654max_body_size = 5242880
655max_request_body = 1048576
656allow_private_ips = true
657"#,
658 );
659 let http = cfg.components.http.unwrap();
660 assert_eq!(http.connect_timeout_ms, 2000);
661 assert_eq!(http.response_timeout_ms, 60000);
662 assert_eq!(http.max_connections, 50);
663 assert_eq!(http.max_body_size, 5_242_880);
664 assert_eq!(http.max_request_body, 1_048_576);
665 assert!(http.allow_private_ips);
666 }
667}
668
669#[cfg(test)]
670mod component_camel_config_tests {
671 use super::*;
672
673 fn parse(toml: &str) -> CamelConfig {
674 let cfg = config::Config::builder()
675 .add_source(config::File::from_str(toml, config::FileFormat::Toml))
676 .build()
677 .unwrap();
678 cfg.try_deserialize().unwrap()
679 }
680
681 #[test]
682 fn test_kafka_defaults() {
683 let cfg = parse("");
684 assert!(cfg.components.kafka.is_none());
685 }
686
687 #[test]
688 fn test_kafka_partial_override() {
689 let cfg = parse(
690 r#"
691[components.kafka]
692brokers = "prod:9092"
693"#,
694 );
695 let k = cfg.components.kafka.unwrap();
696 assert_eq!(k.brokers, "prod:9092");
697 assert_eq!(k.group_id, "camel");
698 assert_eq!(k.session_timeout_ms, 45_000);
699 assert_eq!(k.request_timeout_ms, 30_000);
700 assert_eq!(k.auto_offset_reset, "latest");
701 assert_eq!(k.security_protocol, "plaintext");
702 }
703
704 #[test]
705 fn test_redis_defaults() {
706 let cfg = parse(
707 r#"
708[components.redis]
709port = 6380
710"#,
711 );
712 let r = cfg.components.redis.unwrap();
713 assert_eq!(r.host, "localhost");
714 assert_eq!(r.port, 6380);
715 }
716
717 #[test]
718 fn test_sql_defaults() {
719 let cfg = parse(
720 r#"
721[components.sql]
722max_connections = 10
723"#,
724 );
725 let s = cfg.components.sql.unwrap();
726 assert_eq!(s.max_connections, 10);
727 assert_eq!(s.min_connections, 1);
728 assert_eq!(s.idle_timeout_secs, 300);
729 assert_eq!(s.max_lifetime_secs, 1_800);
730 }
731
732 #[test]
733 fn test_file_defaults() {
734 let cfg = parse(
735 r#"
736[components.file]
737delay_ms = 1000
738"#,
739 );
740 let f = cfg.components.file.unwrap();
741 assert_eq!(f.delay_ms, 1000);
742 assert_eq!(f.initial_delay_ms, 1_000);
743 assert_eq!(f.read_timeout_ms, 30_000);
744 assert_eq!(f.write_timeout_ms, 30_000);
745 }
746
747 #[test]
748 fn test_container_defaults() {
749 let cfg = parse(
750 r#"
751[components.container]
752docker_host = "tcp://remote:2375"
753"#,
754 );
755 let c = cfg.components.container.unwrap();
756 assert_eq!(c.docker_host, "tcp://remote:2375");
757 }
758
759 #[test]
760 fn test_omitted_sections_are_none() {
761 let cfg = parse("");
762 assert!(cfg.components.kafka.is_none());
763 assert!(cfg.components.redis.is_none());
764 assert!(cfg.components.sql.is_none());
765 assert!(cfg.components.file.is_none());
766 assert!(cfg.components.container.is_none());
767 }
768
769 #[test]
770 fn test_kafka_camel_config_default_matches_serde() {
771 let d = KafkaCamelConfig::default();
772 assert_eq!(d.brokers, "localhost:9092");
773 assert_eq!(d.group_id, "camel");
774 assert_eq!(d.session_timeout_ms, 45_000);
775 assert_eq!(d.request_timeout_ms, 30_000);
776 assert_eq!(d.auto_offset_reset, "latest");
777 assert_eq!(d.security_protocol, "plaintext");
778 }
779
780 #[test]
781 fn test_redis_camel_config_default_matches_serde() {
782 let d = RedisCamelConfig::default();
783 assert_eq!(d.host, "localhost");
784 assert_eq!(d.port, 6379);
785 }
786
787 #[test]
788 fn test_sql_camel_config_default_matches_serde() {
789 let d = SqlCamelConfig::default();
790 assert_eq!(d.max_connections, 5);
791 assert_eq!(d.min_connections, 1);
792 assert_eq!(d.idle_timeout_secs, 300);
793 assert_eq!(d.max_lifetime_secs, 1_800);
794 }
795
796 #[test]
797 fn test_file_camel_config_default_matches_serde() {
798 let d = FileCamelConfig::default();
799 assert_eq!(d.delay_ms, 500);
800 assert_eq!(d.initial_delay_ms, 1_000);
801 assert_eq!(d.read_timeout_ms, 30_000);
802 assert_eq!(d.write_timeout_ms, 30_000);
803 }
804
805 #[test]
806 fn test_container_camel_config_default_matches_serde() {
807 let d = ContainerCamelConfig::default();
808 assert_eq!(d.docker_host, "unix:///var/run/docker.sock");
809 }
810}
811
812#[cfg(test)]
813mod prometheus_config_tests {
814 use super::*;
815
816 fn parse(toml: &str) -> CamelConfig {
817 let cfg = config::Config::builder()
818 .add_source(config::File::from_str(toml, config::FileFormat::Toml))
819 .build()
820 .unwrap();
821 cfg.try_deserialize().unwrap()
822 }
823
824 #[test]
825 fn test_prometheus_absent_is_none() {
826 let cfg = parse("");
827 assert!(cfg.observability.prometheus.is_none());
828 }
829
830 #[test]
831 fn test_prometheus_defaults() {
832 let cfg = parse(
833 r#"
834[observability.prometheus]
835enabled = true
836"#,
837 );
838 let p = cfg.observability.prometheus.unwrap();
839 assert!(p.enabled);
840 assert_eq!(p.host, "0.0.0.0");
841 assert_eq!(p.port, 9090);
842 }
843
844 #[test]
845 fn test_prometheus_full() {
846 let cfg = parse(
847 r#"
848[observability.prometheus]
849enabled = true
850host = "127.0.0.1"
851port = 9091
852"#,
853 );
854 let p = cfg.observability.prometheus.unwrap();
855 assert_eq!(p.host, "127.0.0.1");
856 assert_eq!(p.port, 9091);
857 }
858}
859
860#[cfg(all(test, feature = "http"))]
861mod http_from_tests {
862 use crate::config::HttpCamelConfig;
863 use camel_component_http;
864
865 #[test]
866 fn test_http_camel_config_to_http_config() {
867 let camel_cfg = HttpCamelConfig {
868 connect_timeout_ms: 1_000,
869 response_timeout_ms: 5_000,
870 max_connections: 20,
871 max_body_size: 1_000,
872 max_request_body: 500,
873 allow_private_ips: true,
874 };
875 let cfg = camel_component_http::HttpConfig::from(&camel_cfg);
876 assert_eq!(cfg.connect_timeout_ms, 1_000);
877 assert_eq!(cfg.max_connections, 20);
878 assert!(cfg.allow_private_ips);
879 }
880}