33//! zookeeper-operator.
44//!
55//! Differences from upstream:
6- //! - `env_overrides` is `BTreeMap<String, String>` instead of `EnvVarSet`.
76//! - No `cli_overrides_to_vec` helper, `ResourceNames`, or service-account helpers.
87//! - The `CommonConfig` (a.k.a. `product_specific_common_config`) does NOT need to
98//! implement `Merge`. ZooKeeper uses `JavaCommonConfig`, which intentionally does
1413//! Replace with `stackable_operator::v2::role_utils::*` once upstream publishes
1514//! the module.
1615
17- use std:: collections:: BTreeMap ;
16+ use std:: {
17+ collections:: { BTreeMap , HashMap } ,
18+ str:: FromStr ,
19+ } ;
1820
1921use serde:: Serialize ;
22+ use snafu:: { ResultExt , Snafu } ;
2023use stackable_operator:: {
2124 config:: {
2225 fragment:: { self , FromFragment } ,
@@ -25,19 +28,28 @@ use stackable_operator::{
2528 k8s_openapi:: { DeepMerge , api:: core:: v1:: PodTemplateSpec } ,
2629 role_utils:: { Role , RoleGroup } ,
2730 schemars:: JsonSchema ,
31+ v2:: builder:: pod:: container:: { self , EnvVarName , EnvVarSet } ,
2832} ;
2933
34+ #[ derive( Snafu , Debug ) ]
35+ pub enum Error {
36+ #[ snafu( display( "failed to validate the role group config" ) ) ]
37+ ValidateConfig { source : fragment:: ValidationError } ,
38+
39+ #[ snafu( display( "invalid environment variable override name" ) ) ]
40+ ParseEnvVarName { source : container:: Error } ,
41+ }
42+
3043/// A validated, merged view of a `RoleGroup`.
3144///
3245/// Mirrors `stackable_operator::v2::role_utils::RoleGroupConfig` on the
33- /// `smooth-operator` branch, with `env_overrides: BTreeMap<String, String>`
34- /// instead of the upstream `EnvVarSet`.
46+ /// `smooth-operator` branch.
3547#[ derive( Clone , Debug , PartialEq ) ]
3648pub struct RoleGroupConfig < Config , CommonConfig , ConfigOverrides > {
3749 pub replicas : u16 ,
3850 pub config : Config ,
3951 pub config_overrides : ConfigOverrides ,
40- pub env_overrides : BTreeMap < String , String > ,
52+ pub env_overrides : EnvVarSet ,
4153 pub cli_overrides : BTreeMap < String , String > ,
4254 pub pod_overrides : PodTemplateSpec ,
4355 pub product_specific_common_config : CommonConfig ,
@@ -58,18 +70,16 @@ pub fn with_validated_config<ValidatedConfig, CommonConfig, Config, RoleConfig,
5870 role_group : & RoleGroup < Config , CommonConfig , ConfigOverrides > ,
5971 role : & Role < Config , ConfigOverrides , RoleConfig , CommonConfig > ,
6072 default_config : & Config ,
61- ) -> Result <
62- RoleGroupConfig < ValidatedConfig , CommonConfig , ConfigOverrides > ,
63- fragment:: ValidationError ,
64- >
73+ ) -> Result < RoleGroupConfig < ValidatedConfig , CommonConfig , ConfigOverrides > , Error >
6574where
6675 ValidatedConfig : FromFragment < Fragment = Config > ,
6776 CommonConfig : Clone + Default + JsonSchema + Serialize ,
6877 Config : Clone + Merge ,
6978 RoleConfig : Default + JsonSchema + Serialize ,
7079 ConfigOverrides : Clone + Default + JsonSchema + Merge + Serialize ,
7180{
72- let validated_config = validate_config ( role_group, role, default_config) ?;
81+ let validated_config =
82+ validate_config ( role_group, role, default_config) . context ( ValidateConfigSnafu ) ?;
7383 Ok ( RoleGroupConfig {
7484 replicas : role_group. replicas . unwrap_or ( 1 ) ,
7585 config : validated_config,
7888 role_group. config . config_overrides . clone ( ) ,
7989 ) ,
8090 env_overrides : merged_env_overrides (
81- role. config
82- . env_overrides
83- . iter ( )
84- . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) )
85- . collect ( ) ,
86- role_group
87- . config
88- . env_overrides
89- . iter ( )
90- . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) )
91- . collect ( ) ,
92- ) ,
91+ & role. config . env_overrides ,
92+ & role_group. config . env_overrides ,
93+ ) ?,
9394 cli_overrides : merged_cli_overrides (
9495 role. config . cli_overrides . clone ( ) ,
9596 role_group. config . cli_overrides . clone ( ) ,
@@ -128,12 +129,22 @@ where
128129}
129130
130131fn merged_env_overrides (
131- role_env_overrides : BTreeMap < String , String > ,
132- role_group_env_overrides : BTreeMap < String , String > ,
133- ) -> BTreeMap < String , String > {
134- let mut merged = role_env_overrides;
135- merged. extend ( role_group_env_overrides) ;
136- merged
132+ role_env_overrides : & HashMap < String , String > ,
133+ role_group_env_overrides : & HashMap < String , String > ,
134+ ) -> Result < EnvVarSet , Error > {
135+ // Process the role first, then the role group, so that role-group overrides win on key
136+ // collisions (`EnvVarSet::with_value` overrides earlier entries with the same name).
137+ let mut env_overrides = EnvVarSet :: new ( ) ;
138+ for ( name, value) in role_env_overrides
139+ . iter ( )
140+ . chain ( role_group_env_overrides. iter ( ) )
141+ {
142+ env_overrides = env_overrides. with_value (
143+ & EnvVarName :: from_str ( name) . context ( ParseEnvVarNameSnafu ) ?,
144+ value. clone ( ) ,
145+ ) ;
146+ }
147+ Ok ( env_overrides)
137148}
138149
139150fn merged_cli_overrides (
0 commit comments