Skip to content

Commit

Permalink
Env substitution (#203)
Browse files Browse the repository at this point in the history
* Env substitution works

* Move to dev-dependencies

* Formatting

* Ensure that there are no quotes or anything around substitution

* use non normal env vars to avoid future issues
  • Loading branch information
ryardley authored Dec 10, 2024
1 parent 93af147 commit d155714
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 23 deletions.
55 changes: 33 additions & 22 deletions packages/ciphernode/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/ciphernode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ clap = { version = "4.5.17", features = ["derive"] }
cipher = { path = "./cipher" }
dirs = "5.0.1"
data = { path = "./data" }
shellexpand = "3.1.0"
figment = { version = "0.10.19", features = ["yaml", "test"] }
fhe_rs = { package = "fhe", git = "https://github.com/gnosisguild/fhe.rs", version = "0.1.0-beta.7" }
fhe-traits = { git = "https://github.com/gnosisguild/fhe.rs", version = "0.1.0-beta.7" }
Expand All @@ -53,6 +54,7 @@ rand = "0.8.5"
serde = { version = "1.0.208", features = ["derive"] }
sled = "0.34.7"
sha2 = "0.10.8"
tempfile = "3.14.0"
tokio = { version = "1.38", features = ["full"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
Expand Down
5 changes: 5 additions & 0 deletions packages/ciphernode/config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ anyhow = { workspace = true }
serde = { workspace = true }
figment = { workspace = true }
alloy = { workspace = true }
shellexpand = { workspace = true }

[dev-dependencies]
tempfile = { workspace = true }

64 changes: 63 additions & 1 deletion packages/ciphernode/config/src/app_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use std::{
path::{Path, PathBuf},
};

use crate::yaml::load_yaml_with_env;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
pub enum Contract {
Expand Down Expand Up @@ -202,8 +204,10 @@ pub fn load_config(config_file: Option<&str>) -> Result<AppConfig> {
defaults.config_file = file.into();
}

let with_envs = load_yaml_with_env(&defaults.config_file())?;

let config = Figment::from(Serialized::defaults(&defaults))
.merge(Yaml::file(defaults.config_file()))
.merge(Yaml::string(&with_envs))
.extract()?;

Ok(config)
Expand Down Expand Up @@ -445,4 +449,62 @@ chains:
Ok(())
});
}

#[test]
fn test_config_env_vars() {
Jail::expect_with(|jail| {
let home = format!("{}", jail.directory().to_string_lossy());
jail.set_env("HOME", &home);
jail.set_env("XDG_CONFIG_HOME", &format!("{}/.config", home));
jail.set_env("TEST_RPC_URL_PORT", "8545");
jail.set_env("TEST_USERNAME", "envUser");
jail.set_env("TEST_PASSWORD", "envPassword");
jail.set_env(
"TEST_CONTRACT_ADDRESS",
"0x1234567890123456789012345678901234567890",
);

let filename = format!("{}/.config/enclave/config.yaml", home);
let filedir = format!("{}/.config/enclave", home);
jail.create_dir(filedir)?;
jail.create_file(
filename,
r#"
chains:
- name: "hardhat"
rpc_url: "ws://test-endpoint:${TEST_RPC_URL_PORT}"
rpc_auth:
type: "Basic"
credentials:
username: "${TEST_USERNAME}"
password: "${TEST_PASSWORD}"
contracts:
enclave: "${TEST_CONTRACT_ADDRESS}"
ciphernode_registry:
address: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"
deploy_block: 1764352873645
filter_registry: "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9"
"#,
)?;

let config: AppConfig = load_config(None).map_err(|err| err.to_string())?;
let chain = config.chains().first().unwrap();

// Test that environment variables are properly substituted
assert_eq!(chain.rpc_url, "ws://test-endpoint:8545");
assert_eq!(
chain.rpc_auth,
RpcAuth::Basic {
username: "envUser".to_string(),
password: "envPassword".to_string(),
}
);
assert_eq!(
chain.contracts.enclave.address(),
"0x1234567890123456789012345678901234567890"
);

Ok(())
});
}
}
1 change: 1 addition & 0 deletions packages/ciphernode/config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
mod app_config;
mod yaml;
pub use app_config::*;
51 changes: 51 additions & 0 deletions packages/ciphernode/config/src/yaml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use anyhow::Result;
use std::{fs, path::PathBuf};

pub fn load_yaml_with_env(file_path: &PathBuf) -> Result<String> {
// Read the file content to string
let content = match fs::read_to_string(file_path) {
Ok(val) => val,
Err(_) => "".to_string(),
};

// Collect environment variables and perform substitution
Ok(shellexpand::env(&content)?.to_string())
}

#[cfg(test)]
mod tests {
use super::*;
use std::env;
use std::fs::File;
use std::io::Write;
use tempfile::tempdir;

#[test]
fn test_yaml_env_substitution() -> Result<()> {
// Create a temporary directory and file
let dir = tempdir()?;
let file_path = dir.path().join("test.yaml");
let mut file = File::create(&file_path)?;

// Write test YAML content
writeln!(
file,
"database:\n url: $MY_DATABASE_URL\n password: ${{MY_DB_PASSWORD}}"
)?;

// Set environment variables
env::set_var("MY_DATABASE_URL", "postgres://localhost:5432");
env::set_var("MY_DB_PASSWORD", "secret123");

// Test the function
let processed = load_yaml_with_env(&file_path)?;

env::remove_var("MY_DATABASE_URL");
env::remove_var("MY_DB_PASSWORD");

assert!(processed.contains("postgres://localhost:5432"));
assert!(processed.contains("secret123"));

Ok(())
}
}

0 comments on commit d155714

Please sign in to comment.