cloud_node_discovery/
lib.rs1use async_trait::async_trait;
23use serde::Deserialize;
24use std::collections::HashMap;
25use thiserror::Error;
26
27use crate::config::parse_config;
28
29mod config;
30mod providers;
31
32#[derive(Debug, Error)]
33pub enum DiscoveryError {
34 #[error("Invalid configuration: {0}")]
35 ConfigError(String),
36 #[error("Provider error: {0}")]
37 ProviderError(String),
38 #[error("Unknown provider: {0}")]
39 UnknownProvider(String),
40}
41
42#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
43pub struct Node {
44 pub address: String,
45 pub meta: HashMap<String, String>,
46}
47
48#[async_trait]
49pub trait Provider {
50 async fn discover(&self) -> Result<Vec<Node>, DiscoveryError>;
51}
52
53pub struct Discovery {
54 provider: Box<dyn Provider>,
55}
56
57impl Discovery {
58 pub async fn new(provider_name: &str, config: &str) -> Result<Self, DiscoveryError> {
59 let config = parse_config(config)?;
60 println!("{:?}", config);
61 let provider: Box<dyn Provider> = match provider_name {
62 #[cfg(feature = "aws")]
63 "aws" => Box::new(providers::aws::AwsProvider::new(&config).await?),
64 #[cfg(feature = "upcloud")]
65 "upcloud" => Box::new(providers::upcloud::UpcloudProvider::new(&config).await?),
66 _ => return Err(DiscoveryError::UnknownProvider(provider_name.to_string())),
67 };
68
69 Ok(Discovery { provider })
70 }
71
72 pub async fn discover(&self) -> Result<Vec<Node>, DiscoveryError> {
73 self.provider.discover().await
74 }
75}
76
77pub struct DiscoveryBuilder {
78 provider_name: String,
79 config: HashMap<String, String>,
80}
81
82impl DiscoveryBuilder {
83 pub fn new(provider_name: &str) -> Self {
84 Self {
85 provider_name: provider_name.to_string(),
86 config: HashMap::new(),
87 }
88 }
89
90 pub fn with_config(mut self, key: &str, value: &str) -> Self {
91 self.config.insert(key.to_string(), value.to_string());
92 self
93 }
94
95 pub async fn build(self) -> Result<Discovery, DiscoveryError> {
96 Discovery::new(&self.provider_name, &self.config_to_string()).await
97 }
98
99 fn config_to_string(&self) -> String {
100 self.config
101 .iter()
102 .map(|(k, v)| format!("{}={}", k, v))
103 .collect::<Vec<_>>()
104 .join(",")
105 }
106}