Skip to content

Commit 8f92ec9

Browse files
committed
refactor: switch to EnvVarSet
1 parent f753aeb commit 8f92ec9

2 files changed

Lines changed: 37 additions & 21 deletions

File tree

rust/operator-binary/src/controller.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -624,16 +624,8 @@ fn build_rolegroup_statefulset(
624624

625625
metadata_database_connection_details.add_to_container(&mut cb_druid);
626626

627-
// rest of env
628-
let mut rest_env = rg
629-
.env
630-
.iter()
631-
.map(|(k, v)| EnvVar {
632-
name: k.clone(),
633-
value: Some(v.clone()),
634-
..EnvVar::default()
635-
})
636-
.collect::<Vec<_>>();
627+
// rest of env: the validated env overrides, rendered in sorted-by-name order.
628+
let mut rest_env: Vec<EnvVar> = rg.env.clone().into();
637629

638630
if let Some(auth_config) = druid_auth_config {
639631
rest_env.extend(auth_config.get_env_var_mounts(druid, role))
@@ -939,9 +931,12 @@ mod test {
939931
use rstest::*;
940932
use stackable_operator::{
941933
database_connections::drivers::jdbc::JdbcDatabaseConnection,
942-
v2::types::{
943-
kubernetes::{NamespaceName, Uid},
944-
operator::ClusterName,
934+
v2::{
935+
builder::pod::container::EnvVarSet,
936+
types::{
937+
kubernetes::{NamespaceName, Uid},
938+
operator::ClusterName,
939+
},
945940
},
946941
};
947942

@@ -1010,7 +1005,7 @@ mod test {
10101005
merged_config,
10111006
runtime_config: runtime_properties::defaults(&DruidRole::Historical),
10121007
security_config: BTreeMap::new(),
1013-
env: BTreeMap::new(),
1008+
env: EnvVarSet::new(),
10141009
// The test only asserts on runtime.properties, so the rendered jvm.config is irrelevant.
10151010
jvm_config: String::new(),
10161011
};

rust/operator-binary/src/controller/validate.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use std::{
77
borrow::Cow,
88
collections::{BTreeMap, HashMap},
9+
str::FromStr,
910
};
1011

1112
use snafu::{ResultExt, Snafu};
@@ -18,6 +19,7 @@ use stackable_operator::{
1819
kube::{Resource, api::ObjectMeta},
1920
v2::{
2021
HasName, HasUid,
22+
builder::pod::container::{self, EnvVarName, EnvVarSet},
2123
controller_utils::{get_cluster_name, get_namespace, get_uid},
2224
types::{
2325
kubernetes::{NamespaceName, Uid},
@@ -76,6 +78,9 @@ pub enum Error {
7678
InvalidMetadataDatabaseConnection {
7779
source: stackable_operator::database_connections::Error,
7880
},
81+
82+
#[snafu(display("invalid environment variable override name"))]
83+
ParseEnvVarName { source: container::Error },
7984
}
8085

8186
type Result<T, E = Error> = std::result::Result<T, E>;
@@ -92,8 +97,9 @@ pub struct DruidRoleGroupConfig {
9297
pub runtime_config: BTreeMap<String, String>,
9398
/// The security.properties "validated config".
9499
pub security_config: BTreeMap<String, String>,
95-
/// Merged env overrides (role <- rolegroup). Druid has no computed env vars.
96-
pub env: BTreeMap<String, String>,
100+
/// Merged env overrides (role <- rolegroup). Druid has no computed env vars. Names are
101+
/// validated here so the build step can render them directly into the container.
102+
pub env: EnvVarSet,
97103
/// The fully rendered `jvm.config` (operator defaults merged with the role/rolegroup JVM
98104
/// argument overrides). Precomputed here so the config-map builder no longer needs the raw
99105
/// cluster's `get_role`.
@@ -228,6 +234,25 @@ fn key_value_overrides(
228234
.collect()
229235
}
230236

237+
/// Merges the role-level and rolegroup-level env overrides into a validated [`EnvVarSet`].
238+
///
239+
/// The role is processed first, then the rolegroup, so that rolegroup overrides win on key
240+
/// collisions ([`EnvVarSet::with_value`] overrides earlier entries with the same name). The
241+
/// override names are validated here so the build step can render them directly.
242+
fn merged_env_overrides(
243+
role_env_overrides: &HashMap<String, String>,
244+
rg_env_overrides: &HashMap<String, String>,
245+
) -> Result<EnvVarSet> {
246+
let mut env = EnvVarSet::new();
247+
for (name, value) in role_env_overrides.iter().chain(rg_env_overrides.iter()) {
248+
env = env.with_value(
249+
&EnvVarName::from_str(name).context(ParseEnvVarNameSnafu)?,
250+
value.clone(),
251+
);
252+
}
253+
Ok(env)
254+
}
255+
231256
/// Builds the precomputed per-file config for a single rolegroup. Pure assembly: combines the
232257
/// role-level overrides with the rolegroup-level overrides (rolegroup wins) on top of the
233258
/// computed defaults. No behavior change vs. the inline loop body it was extracted from.
@@ -269,11 +294,7 @@ fn build_role_group_config(
269294
security_config.extend(security_properties::build(&security_overrides));
270295

271296
// ----- env -----
272-
let mut env: BTreeMap<String, String> = role_env_overrides
273-
.iter()
274-
.map(|(k, v)| (k.clone(), v.clone()))
275-
.collect();
276-
env.extend(rg_env_overrides.iter().map(|(k, v)| (k.clone(), v.clone())));
297+
let env = merged_env_overrides(role_env_overrides, rg_env_overrides)?;
277298

278299
// ----- jvm.config -----
279300
let (heap, direct) = merged_config

0 commit comments

Comments
 (0)