rust_cloud_discovery/
lib.rs

1//! Intended to be rust counterpart of Spring Cloud Discovery client.
2//!
3//! ### Implementations
4//! * Kubernetes - https://github.com/eipi1/cloud-discovery-kubernetes
5//!
6
7use async_trait::async_trait;
8use getset::Getters;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::error::Error;
12
13#[derive(Debug, Getters, Clone, Serialize, Deserialize)]
14pub struct Port {
15    name: Option<String>,
16    port: u32,
17    protocol: String,
18    app_protocol: Option<String>,
19}
20
21impl Port {
22    pub fn new(
23        name: Option<String>,
24        port: u32,
25        protocol: String,
26        app_protocol: Option<String>,
27    ) -> Self {
28        Self {
29            name,
30            port,
31            protocol,
32            app_protocol,
33        }
34    }
35
36    pub fn get_name(&self) -> &Option<String> {
37        &self.name
38    }
39
40    pub fn get_port(&self) -> u32 {
41        self.port
42    }
43
44    pub fn get_protocol(&self) -> &str {
45        &self.protocol
46    }
47
48    pub fn get_app_protocol(&self) -> &Option<String> {
49        &self.app_protocol
50    }
51}
52
53/// Represents an instance
54#[derive(Debug, Getters, Clone, Serialize, Deserialize)]
55pub struct ServiceInstance {
56    #[getset(get = "pub")]
57    instance_id: Option<String>,
58    #[getset(get = "pub")]
59    service_id: Option<String>,
60    host: Option<String>,
61    ports: Option<Vec<Port>>,
62    //org.springframework.cloud.kubernetes.discovery.DefaultIsServicePortSecureResolver#resolve
63    secure: bool,
64    #[getset(get = "pub")]
65    uri: Option<String>,
66    #[getset(get = "pub")]
67    metadata: HashMap<String, String>,
68    #[getset(get = "pub")]
69    scheme: Option<String>,
70}
71
72impl ServiceInstance {
73    #[allow(clippy::too_many_arguments)]
74    pub fn new(
75        instance_id: Option<String>,
76        service_id: Option<String>,
77        host: Option<String>,
78        ports: Option<Vec<Port>>,
79        secure: bool,
80        uri: Option<String>,
81        metadata: HashMap<String, String>,
82        scheme: Option<String>,
83    ) -> Self {
84        ServiceInstance {
85            instance_id,
86            service_id,
87            host,
88            ports,
89            secure,
90            uri,
91            metadata,
92            scheme,
93        }
94    }
95
96    /// get host/IP of the instance
97    pub fn host(&self) -> &Option<String> {
98        &self.host
99    }
100
101    /// get all available ports
102    pub fn get_ports(&self) -> &Option<Vec<Port>> {
103        &self.ports
104    }
105
106    /// Get if the default port uses TLS.
107    /// Selection of default port depends on the implementation
108    pub fn is_secure(&self) -> bool {
109        self.secure
110    }
111}
112
113/// All discovery service provider must implement the trait. Note that, it's based on [async_trait](https://docs.rs/async-trait)
114#[async_trait]
115pub trait DiscoveryService {
116    /// Returns list of instances
117    async fn discover_instances(&self) -> Result<Vec<ServiceInstance>, Box<dyn Error>>;
118}
119
120/// Bridge between [DiscoveryService] and their clients.
121#[allow(dead_code)]
122pub struct DiscoveryClient<T> {
123    service: T,
124}
125
126#[allow(dead_code)]
127impl<T: DiscoveryService> DiscoveryClient<T> {
128    pub fn new(ds: T) -> DiscoveryClient<T> {
129        DiscoveryClient { service: ds }
130    }
131
132    /// Returns a list of discovered instances
133    pub async fn get_instances(&self) -> Result<Vec<ServiceInstance>, Box<dyn Error>> {
134        self.service.discover_instances().await
135    }
136}