1use crate::repository::rust::RustRepo;
2use crate::repository::types::IOInstance;
3use std::fs;
4use std::path::Path;
5
6use crate::exposed::{ExposedEndpointBackend, ExposedEndpointInstance};
7use url::Url;
8use crate::{
9 ArtifactFormat, HolgerConfig, RepositoryInstance, RepositoryBackend, StorageEndpointInstance,
10 RepositoryType, StorageType,
11};
12use std::collections::HashMap;
13use std::sync::Arc;
14use anyhow::Result;
15use crate::exposed::http2::Http2Backend;
16
17pub fn factory(config: &HolgerConfig) -> Result<HolgerInstance> {
18 let mut storage_map: HashMap<String, Arc<StorageEndpointInstance>> = HashMap::new();
20 let mut storage_endpoints = Vec::new();
21
22 for se in &config.storage_endpoints {
23 let instance = Arc::new(StorageEndpointInstance::from_config(se)?);
24 storage_map.insert(se.name.clone(), instance.clone());
25 storage_endpoints.push(instance);
26 }
27
28 let mut endpoint_map: HashMap<String, Arc<ExposedEndpointInstance>> = HashMap::new();
30 let mut exposed_endpoints = Vec::new();
31
32 for ep in &config.exposed_endpoints {
33 let backend: Arc<Http2Backend> = Http2Backend::from_config(
35 ep.name.clone(),
36 &ep.url_prefix,
37 &ep.cert,
38 &ep.key,
39 )?;
40
41 let backend_arc: Arc<dyn ExposedEndpointBackend> = backend.clone();
43
44 let (ip, port) = parse_ip_port(&ep.url_prefix);
45 let instance = Arc::new(ExposedEndpointInstance {
46 name: ep.name.clone(),
47 ip,
48 port,
49 routes: HashMap::new(),
50 backend: backend_arc,
51 });
52
53 endpoint_map.insert(ep.name.clone(), instance.clone());
54 exposed_endpoints.push(instance);
55 }
56
57 let resolve_storage = |name: &str| {
59 storage_map
60 .get(name)
61 .cloned()
62 .ok_or_else(|| anyhow::anyhow!("Storage endpoint '{}' not found", name))
63 };
64
65 let resolve_endpoint = |name: &str| {
66 endpoint_map
67 .get(name)
68 .cloned()
69 .ok_or_else(|| anyhow::anyhow!("Exposed endpoint '{}' not found", name))
70 };
71
72 let mut repositories = Vec::new();
74 for r in &config.repositories {
75 let repo = Arc::new(RepositoryInstance::from_config(
76 r,
77 &resolve_storage,
78 &resolve_endpoint,
79 )?);
80 repositories.push(repo);
81 }
82
83 for repo in &repositories {
85 if let Some(out_io) = &repo.out_io {
86 let ep_name = &out_io.endpoint.name;
87 if let Some(endpoint_arc) = endpoint_map.get(ep_name) {
88 }
94 }
95 }
96
97 Ok(HolgerInstance {
98 exposed_endpoints,
99 storage_endpoints,
100 repositories,
101 })
102}
103fn parse_ip_port(url: &str) -> (String, u16) {
105 let clean = url.trim_end_matches('/');
106 let without_scheme = clean.split("://").nth(1).unwrap_or(clean);
107 let mut parts = without_scheme.split(':');
108 let ip = parts.next().unwrap_or("127.0.0.1").to_string();
109 let port = parts.next().and_then(|p| p.parse().ok()).unwrap_or(443);
110 (ip, port)
111}
112
113
114
115pub fn load_config_from_path<P: AsRef<Path>>(path: P) -> Result<HolgerConfig> {
116 let data = fs::read_to_string(path)?;
117 let config: HolgerConfig = toml::from_str(&data)?;
118 Ok(config)
119}
120
121#[derive(Debug)]
122pub struct HolgerInstance {
123 pub exposed_endpoints: Vec<Arc<ExposedEndpointInstance>>,
124 pub storage_endpoints: Vec<Arc<StorageEndpointInstance>>,
125 pub repositories: Vec<Arc<RepositoryInstance>>,
126}
127
128impl HolgerInstance {
129 pub fn start(&self) -> anyhow::Result<()> {
130 self.exposed_endpoints
131 .iter()
132 .map(|ep| ep.backend.as_ref()) .try_for_each(|backend| backend.start())?;
134 Ok(())
135 }
136
137 pub fn stop(&self) -> anyhow::Result<()> {
138 self.exposed_endpoints
139 .iter()
140 .map(|ep| ep.backend.as_ref())
141 .try_for_each(|backend| backend.stop())?;
142 Ok(())
143 }
144}
145