nullnet_libdatastore/config.rs
1use nullnet_liberror::{Error, ErrorHandler, Location, location};
2use tonic::transport::{Channel, ClientTlsConfig};
3
4/// Configuration structure for the datastore.
5///
6/// This struct encapsulates the configuration details required to connect to the datastore,
7/// including the host address, port, and whether TLS is enabled.
8#[derive(Debug, Clone)]
9pub struct DatastoreConfig {
10 /// Hostname or IP address of the datastore.
11 pub host: String,
12 /// Port number used to connect to the datastore.
13 pub port: u16,
14 /// Whether TLS is enabled for the datastore connection.
15 pub tls: bool,
16}
17
18impl DatastoreConfig {
19 /// Creates a new `DatastoreConfig` instance by reading values from environment variables.
20 ///
21 /// If the environment variables are not set or cannot be parsed, default values are used:
22 /// - `DATASTORE_HOST` defaults to `"127.0.0.1"`.
23 /// - `DATASTORE_PORT` defaults to `6000`.
24 /// - `DATASTORE_TLS` defaults to `false`.
25 ///
26 /// # Returns
27 /// A `DatastoreConfig` instance with values derived from the environment or defaults.
28 #[must_use]
29 pub fn from_env() -> Self {
30 Self {
31 host: read_host_value_from_env(String::from("127.0.0.1")),
32 port: read_port_value_from_env(6000),
33 tls: real_tls_value_from_env(false),
34 }
35 }
36
37 /// Creates a new `DatastoreConfig` instance with the provided values.
38 ///
39 /// # Arguments
40 /// * `host` - A `String` representing the hostname or IP address of the datastore.
41 /// * `port` - A `u16` representing the port number for connecting to the datastore.
42 /// * `tls` - A `bool` indicating whether to use TLS for the connection (`true` for TLS, `false` otherwise).
43 ///
44 /// # Returns
45 /// A `DatastoreConfig` instance initialized with the specified host, port, and TLS settings.
46 #[must_use]
47 pub fn new(host: String, port: u16, tls: bool) -> Self {
48 Self { host, port, tls }
49 }
50
51 /// Establishes a connection to the datastore service.
52 ///
53 /// # Returns
54 /// * `Ok(Channel)` - Opened channel.
55 /// * `Err(Error)` - If the connection fails.
56 pub(crate) async fn connect(&self) -> Result<Channel, Error> {
57 let protocol = if self.tls { "https" } else { "http" };
58 let host = self.host.as_str();
59 let port = self.port;
60
61 let mut endpoint = Channel::from_shared(format!("{protocol}://{host}:{port}"))
62 .handle_err(location!())?
63 .connect_timeout(std::time::Duration::from_secs(10));
64
65 if self.tls {
66 endpoint = endpoint
67 .tls_config(ClientTlsConfig::new().with_native_roots())
68 .handle_err(location!())?;
69 }
70
71 let channel = endpoint.connect().await.handle_err(location!())?;
72
73 Ok(channel)
74 // Ok(StoreServiceClient::new(channel).max_decoding_message_size(50 * 1024 * 1024))
75 }
76}
77
78/// Reads the `DATASTORE_HOST` environment variable.
79///
80/// If the variable is not set or an error occurs, the specified default value is returned.
81///
82/// # Parameters
83/// - `default`: Default hostname to use if the environment variable is not set.
84///
85/// # Returns
86/// The value of `DATASTORE_HOST` or the default value if the variable is not set.
87fn read_host_value_from_env(default: String) -> String {
88 std::env::var("DATASTORE_HOST").unwrap_or_else(|err| {
89 log::warn!("Failed to read 'DATASTORE_HOST' env var: {err}. Using default value ...");
90 default
91 })
92}
93
94/// Reads the `DATASTORE_PORT` environment variable and parses it as a `u16`.
95///
96/// If the variable is not set, cannot be parsed, or an error occurs, the specified default value is used.
97///
98/// # Parameters
99/// - `default`: Default port to use if the environment variable is not set or invalid.
100///
101/// # Returns
102/// The value of `DATASTORE_PORT` parsed as a `u16` or the default value if the variable is not set or invalid.
103fn read_port_value_from_env(default: u16) -> u16 {
104 match std::env::var("DATASTORE_PORT") {
105 Ok(value) => value.parse::<u16>().unwrap_or_else(|err| {
106 log::warn!(
107 "Failed to parse 'DATASTORE_PORT' ({value}) as u16: {err}. Using default value ..."
108 );
109 default
110 }),
111 Err(err) => {
112 log::warn!("Failed to read 'DATASTORE_PORT' env var: {err}. Using default value ...");
113 default
114 }
115 }
116}
117
118/// Reads the `DATASTORE_TLS` environment variable and interprets it as a boolean.
119///
120/// If the variable is set to `"true"` (case insensitive), it returns `true`. For any other value or
121/// if the variable is not set, the specified default value is used.
122///
123/// # Parameters
124/// - `default`: Default value to use if the environment variable is not set.
125///
126/// # Returns
127/// `true` if the environment variable is set to `"true"`, otherwise the default value.
128fn real_tls_value_from_env(default: bool) -> bool {
129 match std::env::var("DATASTORE_TLS") {
130 Ok(value) => value.to_lowercase() == "true",
131 Err(err) => {
132 log::warn!("Failed to read 'DATASTORE_TLS' env var: {err}. Using default value ...");
133 default
134 }
135 }
136}