Browse Source

support env var in yaml config

0xfirefist 1 year ago
parent
commit
90c7496293
4 changed files with 57 additions and 9 deletions
  1. 21 7
      fortuna/Cargo.lock
  2. 2 0
      fortuna/Cargo.toml
  3. 30 2
      fortuna/src/config.rs
  4. 4 0
      fortuna/src/main.rs

+ 21 - 7
fortuna/Cargo.lock

@@ -960,6 +960,12 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "dotenv"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
+
 [[package]]
 name = "dtoa"
 version = "1.0.9"
@@ -1496,6 +1502,7 @@ dependencies = [
  "bincode",
  "byteorder",
  "clap",
+ "dotenv",
  "ethabi",
  "ethers",
  "hex",
@@ -1504,6 +1511,7 @@ dependencies = [
  "prometheus-client",
  "pythnet-sdk",
  "rand",
+ "regex",
  "reqwest",
  "serde",
  "serde_json",
@@ -2930,14 +2938,14 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.9.6"
+version = "1.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff"
+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-automata 0.3.9",
- "regex-syntax 0.7.5",
+ "regex-automata 0.4.3",
+ "regex-syntax 0.8.2",
 ]
 
 [[package]]
@@ -2951,13 +2959,13 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.3.9"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax 0.7.5",
+ "regex-syntax 0.8.2",
 ]
 
 [[package]]
@@ -2972,6 +2980,12 @@ version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
 
+[[package]]
+name = "regex-syntax"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+
 [[package]]
 name = "reqwest"
 version = "0.11.22"

+ 2 - 0
fortuna/Cargo.toml

@@ -32,6 +32,8 @@ utoipa             = { version = "3.4.0", features = ["axum_extras"] }
 utoipa-swagger-ui  = { version = "3.1.4", features = ["axum"] }
 once_cell = "1.18.0"
 lazy_static = "1.4.0"
+dotenv = "0.15.0"
+regex = "1.10.2"
 
 [dev-dependencies]
 axum-test = "13.1.1"

+ 30 - 2
fortuna/src/config.rs

@@ -1,3 +1,5 @@
+use std::{env::VarError, borrow::Borrow};
+
 use {
     crate::{
         api::ChainId,
@@ -6,6 +8,7 @@ use {
     anyhow::{
         anyhow,
         Result,
+        Error
     },
     clap::{
         crate_authors,
@@ -16,8 +19,13 @@ use {
         Parser,
     },
     ethers::types::Address,
+    regex::{
+        Captures,
+        Regex,
+    },
     std::{
         collections::HashMap,
+        env,
         fs,
     },
 };
@@ -105,16 +113,36 @@ impl Config {
         // Open and read the YAML file
         // TODO: the default serde deserialization doesn't enforce unique keys
         let yaml_content = fs::read_to_string(path)?;
-        let config: Config = serde_yaml::from_str(&yaml_content)?;
+        let config: Config = serde_yaml::from_str(Config::inject_env(&yaml_content)?.as_str())?;
         Ok(config)
     }
 
     pub fn get_chain_config(&self, chain_id: &ChainId) -> Result<EthereumConfig> {
         self.chains
             .get(chain_id)
-            .map(|x| x.clone())
+            .map(|x: &EthereumConfig| x.clone())
             .ok_or(anyhow!("Could not find chain id {} in the configuration", &chain_id).into())
     }
+
+    fn inject_env(yaml_content: &str) -> Result<String> {
+        let re = Regex::new(r"\$\{([a-zA-Z_][0-9a-zA-Z_]*)\}").unwrap();
+        let mut var_error: Option<env::VarError>= None;
+        let new_yaml_content = re.replace_all(&yaml_content, |caps: &Captures| {
+            match env::var(&caps[1]) {
+                Ok(val) => val,
+                Err(err) => {
+                    var_error = Some(err);
+                    (&caps[0]).to_string()
+                },
+            }
+        });
+
+        if let Some(error) = var_error {
+            Err(anyhow!("Missing env var: {}", error))
+        } else {
+            Ok(new_yaml_content.to_string())
+        }
+    }
 }
 
 #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]

+ 4 - 0
fortuna/src/main.rs

@@ -5,6 +5,7 @@ use {
     anyhow::Result,
     clap::Parser,
     std::io::IsTerminal,
+    dotenv::dotenv,
 };
 
 pub mod api;
@@ -22,6 +23,9 @@ pub mod state;
 #[tokio::main]
 #[tracing::instrument]
 async fn main() -> Result<()> {
+    // Load the environment variable from .env file
+    dotenv().ok();
+
     // Initialize a Tracing Subscriber
     tracing::subscriber::set_global_default(
         tracing_subscriber::fmt()