This is an automated email from the ASF dual-hosted git repository.
spetz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new 30bdb469b fix(configs): allow sibling IGGY variables (#4149)
30bdb469b is described below
commit 30bdb469b9525c3d7e0faa4758326d8c8ab13ef7
Author: Rudra Prasad Bhuyan <[email protected]>
AuthorDate: Sun Sep 13 21:06:54 2026 +0530
fix(configs): allow sibling IGGY variables (#4149)
Closes #4143
---
Cargo.lock | 1 +
core/configs/Cargo.toml | 3 +++
core/configs/src/configs_impl/file_provider.rs | 28 +++++++++++++++++-----
.../configs/src/configs_impl/typed_env_provider.rs | 1 +
core/configs/src/server_config/server.rs | 6 +++++
5 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 5a191fc13..8e0573eca 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3248,6 +3248,7 @@ dependencies = [
"serde",
"serde_json",
"serde_with",
+ "serial_test",
"server_common",
"static-toml",
"tracing",
diff --git a/core/configs/Cargo.toml b/core/configs/Cargo.toml
index a1f5d5142..2649bf37d 100644
--- a/core/configs/Cargo.toml
+++ b/core/configs/Cargo.toml
@@ -37,5 +37,8 @@ server_common = { workspace = true }
static-toml = { workspace = true }
tracing = { workspace = true }
+[dev-dependencies]
+serial_test = { workspace = true }
+
[lints]
workspace = true
diff --git a/core/configs/src/configs_impl/file_provider.rs
b/core/configs/src/configs_impl/file_provider.rs
index f384352fd..f182f2cd2 100644
--- a/core/configs/src/configs_impl/file_provider.rs
+++ b/core/configs/src/configs_impl/file_provider.rs
@@ -71,6 +71,7 @@ pub struct FileConfigProvider<P> {
env_prefix: &'static str,
relocated_keys: &'static [RelocatedKey],
known_env_names: Option<Vec<&'static str>>,
+ allowed_env_prefixes: &'static [&'static str],
}
impl<P: Provider> FileConfigProvider<P> {
@@ -95,6 +96,7 @@ impl<P: Provider> FileConfigProvider<P> {
env_prefix: "",
relocated_keys: &[],
known_env_names: None,
+ allowed_env_prefixes: &[],
}
}
@@ -120,6 +122,11 @@ impl<P: Provider> FileConfigProvider<P> {
self
}
+ pub fn with_allowed_env_prefixes(mut self, prefixes: &'static [&'static
str]) -> Self {
+ self.allowed_env_prefixes = prefixes;
+ self
+ }
+
fn reject_unknown_env_names(&self) -> Result<(), ConfigurationError> {
let Some(known) = &self.known_env_names else {
return Ok(());
@@ -128,9 +135,10 @@ impl<P: Provider> FileConfigProvider<P> {
env::vars_os().filter_map(|(name, _)| name.into_string().ok()),
self.env_prefix,
known,
+ self.allowed_env_prefixes,
);
for name in &unknown {
- eprintln!("Unknown configuration environment variable '{name}'");
+ eprintln!("Unknown configuration environment variable '{name}'.
Unset it to boot.");
}
let rejected = !unknown.is_empty();
if rejected {
@@ -279,9 +287,16 @@ fn unknown_env_names(
names: impl Iterator<Item = String>,
prefix: &str,
known: &[&str],
+ allowed_prefixes: &[&str],
) -> Vec<String> {
names
- .filter(|name| name.starts_with(prefix) &&
!known.contains(&name.as_str()))
+ .filter(|name| {
+ name.starts_with(prefix)
+ && !known.contains(&name.as_str())
+ && !allowed_prefixes
+ .iter()
+ .any(|allowed| name.starts_with(allowed))
+ })
.collect()
}
@@ -339,6 +354,7 @@ mod tests {
.into_iter(),
"IGGY_",
&["IGGY_TCP_ADDRESS", "IGGY_ROOT_PASSWORD"],
+ &[],
);
assert_eq!(unknown, vec!["IGGY_ENCRYPTION_UNKNOWN"]);
}
@@ -407,7 +423,6 @@ mod tests {
/// environment, a shared `env_file`, or the `.env` that `main.rs` loads
/// through `dotenvy` before `load_config` runs will refuse server boot.
#[test]
- #[ignore = "PR #4092 review: the `IGGY_` prefix fence refuses the repo's
own `IGGY_CONNECTORS_*`, `IGGY_MCP_*` and CLI variables, with no opt-out"]
fn
given_a_sibling_binarys_env_vars_when_rejecting_then_the_server_should_still_boot()
{
let siblings = [
"IGGY_CONNECTORS_CONFIG_PATH",
@@ -422,8 +437,8 @@ mod tests {
names(&siblings).into_iter(),
"IGGY_",
crate::server_config::server::SERVER_PROCESS_ENV_VARS,
+ crate::server_config::server::SERVER_ALLOWED_ENV_PREFIXES,
);
-
assert!(
unknown.is_empty(),
"the server refuses to boot when its own sibling products'
variables are present: {unknown:?}"
@@ -449,7 +464,7 @@ mod tests {
/// Mutates the process environment, so it must not run beside another test
/// that reads it.
#[test]
- #[ignore = "PR #4092 review: a `.env` loaded by `dotenvy` before
`load_config` refuses server boot; also mutates the process environment, so it
must not run in parallel"]
+ #[serial_test::serial]
fn
given_a_dotenv_with_a_connectors_variable_when_loading_then_the_server_should_boot()
{
// SAFETY: single-threaded assertion over a variable no other test
reads.
unsafe { std::env::set_var("IGGY_CONNECTORS_CONFIG_PATH",
"/etc/iggy/connectors.toml") };
@@ -461,7 +476,8 @@ mod tests {
None,
)
.with_relocated_keys("IGGY_", &[])
-
.with_known_env_names(crate::server_config::server::SERVER_PROCESS_ENV_VARS.to_vec());
+
.with_known_env_names(crate::server_config::server::SERVER_PROCESS_ENV_VARS.to_vec())
+
.with_allowed_env_prefixes(crate::server_config::server::SERVER_ALLOWED_ENV_PREFIXES);
let rejected = provider.reject_unknown_env_names();
// SAFETY: paired with the set above.
diff --git a/core/configs/src/configs_impl/typed_env_provider.rs
b/core/configs/src/configs_impl/typed_env_provider.rs
index 72ac9fe01..5225f6a8a 100644
--- a/core/configs/src/configs_impl/typed_env_provider.rs
+++ b/core/configs/src/configs_impl/typed_env_provider.rs
@@ -584,6 +584,7 @@ mod tests {
}
#[test]
+ #[serial_test::serial]
fn typed_provider_deserializes_env_vars() {
unsafe {
env::set_var("TEST_ENABLED", "true");
diff --git a/core/configs/src/server_config/server.rs
b/core/configs/src/server_config/server.rs
index 2420fcc07..c2a3455a0 100644
--- a/core/configs/src/server_config/server.rs
+++ b/core/configs/src/server_config/server.rs
@@ -61,8 +61,13 @@ pub const SERVER_PROCESS_ENV_VARS: &[&str] = &[
"IGGY_SHARD_RUNTIME_CAPACITY",
"IGGY_SHARD_EVENT_INTERVAL",
"IGGY_CI_BUILD",
+ "IGGY_HOME",
+ "IGGY_USERNAME",
+ "IGGY_PASSWORD",
];
+pub(crate) const SERVER_ALLOWED_ENV_PREFIXES: &[&str] = &["IGGY_CONNECTORS_",
"IGGY_MCP_"];
+
const DEFAULT_CONFIG_PATH: &str = "core/server/config.toml";
/// Server config keys that became per-topic options, or went away with the
@@ -261,6 +266,7 @@ impl ServerConfig {
.chain(SERVER_PROCESS_ENV_VARS.iter().copied())
.collect(),
)
+ .with_allowed_env_prefixes(SERVER_ALLOWED_ENV_PREFIXES)
}
/// All recognised env var names for [`ServerConfig`].