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`].

Reply via email to