1use anyhow::{Context, Result};
4use core::time::Duration;
5use serde::{Deserialize, Serialize, de::DeserializeOwned};
6use serde_with::{DurationSeconds, serde_as};
7use std::net::SocketAddr;
8use tracing::debug;
9
10#[serde_as]
11#[derive(Clone, Debug, Deserialize, Serialize)]
12#[serde(rename_all = "kebab-case")]
13pub struct ProxyConfig {
14 pub network: String,
15 pub listen_address: SocketAddr,
16 pub remote_write: RemoteWriteConfig,
17 pub dynamic_peers: DynamicPeerValidationConfig,
18 pub static_peers: Option<StaticPeerValidationConfig>,
19 pub metrics_address: String,
20 pub histogram_address: String,
21}
22
23#[serde_as]
24#[derive(Clone, Debug, Deserialize, Serialize, Default)]
25#[serde(rename_all = "kebab-case")]
26pub struct RemoteWriteConfig {
27 #[serde(default = "remote_write_url")]
30 pub url: String,
31 pub username: String,
33 pub password: String,
34
35 #[serde(default = "pool_max_idle_per_host_default")]
38 pub pool_max_idle_per_host: usize,
39}
40
41#[serde_as]
48#[derive(Clone, Debug, Deserialize, Serialize)]
49#[serde(rename_all = "kebab-case")]
50pub struct DynamicPeerValidationConfig {
51 pub url: String,
53 #[serde_as(as = "DurationSeconds<u64>")]
54 pub interval: Duration,
55 #[serde(default = "hostname_default")]
58 pub hostname: Option<String>,
59
60 pub certificate_file: Option<String>,
63 pub private_key: Option<String>,
66
67 pub hashi_object_id: Option<String>,
70}
71
72#[serde_as]
75#[derive(Clone, Debug, Deserialize, Serialize)]
76#[serde(rename_all = "kebab-case")]
77pub struct StaticPeerValidationConfig {
78 pub pub_keys: Vec<StaticPubKey>,
79}
80
81#[serde_as]
84#[derive(Clone, Debug, Deserialize, Serialize)]
85#[serde(rename_all = "kebab-case")]
86pub struct StaticPubKey {
87 pub name: String,
89 pub peer_id: String,
91}
92
93fn pool_max_idle_per_host_default() -> usize {
95 8
96}
97
98fn hostname_default() -> Option<String> {
100 Some("localhost".to_string())
101}
102
103fn remote_write_url() -> String {
105 "http://metrics-gw.testnet.sui.io/api/v1/push".to_string()
106}
107
108pub fn load<P: AsRef<std::path::Path>, T: DeserializeOwned + Serialize>(path: P) -> Result<T> {
110 let path = path.as_ref();
111 debug!("Reading config from {:?}", path);
112 Ok(serde_yaml::from_reader(
113 std::fs::File::open(path).context(format!("cannot open {:?}", path))?,
114 )?)
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 #[test]
121 fn config_load() {
122 const TEMPLATE: &str = include_str!("./data/config.yaml");
123
124 let _template: ProxyConfig = serde_yaml::from_str(TEMPLATE).unwrap();
125 }
126}