Skip to content

Commit 6210963

Browse files
committed
refactor: remove HbaseCluster::merged_config, dedup merge via with_validated_config
1 parent 1a4e708 commit 6210963

3 files changed

Lines changed: 130 additions & 156 deletions

File tree

rust/operator-binary/src/controller/build/jvm.rs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,6 @@ fn is_heap_jvm_argument(jvm_argument: &str) -> bool {
9797

9898
#[cfg(test)]
9999
mod tests {
100-
use stackable_operator::config::merge::Merge;
101-
102100
use super::*;
103101
use crate::crd::{HbaseRole, v1alpha1};
104102

@@ -212,23 +210,16 @@ mod tests {
212210
let hbase: v1alpha1::HbaseCluster =
213211
serde_yaml::from_str(hbase_cluster).expect("illegal test input");
214212

215-
let hbase_role = HbaseRole::RegionServer;
216-
let merged_config = hbase
217-
.merged_config(&hbase_role, "default", "my-hdfs")
218-
.unwrap();
219-
220-
// Merge the role <- role-group JVM argument overrides the same way
221-
// `with_validated_config` does, so the tests exercise the real merge path.
222-
let role = hbase.spec.region_servers.as_ref().unwrap();
223-
let mut merged_common = role
224-
.role_groups
225-
.get("default")
226-
.unwrap()
227-
.config
228-
.product_specific_common_config
229-
.clone();
230-
merged_common.merge(&role.config.product_specific_common_config);
231-
let merged_jvm_argument_overrides = merged_common.jvm_argument_overrides;
213+
// Merge + validate the region server `default` role group via the real
214+
// `with_validated_config` path, returning the merged config (for heap sizing) and the
215+
// merged JVM argument overrides.
216+
let (merged_config, merged_jvm_argument_overrides) =
217+
crate::crd::test_helpers::merged_role_group_config(
218+
&hbase,
219+
&HbaseRole::RegionServer,
220+
"default",
221+
"my-hdfs",
222+
);
232223

233224
(hbase, merged_config, merged_jvm_argument_overrides)
234225
}

rust/operator-binary/src/crd/affinity.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,13 @@ mod tests {
124124
"#;
125125
let hbase: v1alpha1::HbaseCluster =
126126
serde_yaml::from_str(input).expect("illegal test input");
127-
let affinity = hbase
128-
.merged_config(
129-
&role,
130-
"default",
131-
&hbase.spec.cluster_config.hdfs_config_map_name,
132-
)
133-
.unwrap()
134-
.affinity()
135-
.clone();
127+
let (merged_config, _) = crate::crd::test_helpers::merged_role_group_config(
128+
&hbase,
129+
&role,
130+
"default",
131+
&hbase.spec.cluster_config.hdfs_config_map_name,
132+
);
133+
let affinity = merged_config.affinity().clone();
136134

137135
let mut expected_affinities = vec![WeightedPodAffinityTerm {
138136
pod_affinity_term: PodAffinityTerm {

rust/operator-binary/src/crd/mod.rs

Lines changed: 113 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::BTreeMap;
33
use security::AuthenticationConfig;
44
use serde::{Deserialize, Serialize};
55
use shell_escape::escape;
6-
use snafu::{OptionExt, ResultExt, Snafu};
6+
use snafu::{ResultExt, Snafu};
77
use stackable_operator::{
88
builder::pod::volume::{
99
ListenerOperatorVolumeSourceBuilder, ListenerOperatorVolumeSourceBuilderError,
@@ -19,15 +19,15 @@ use stackable_operator::{
1919
},
2020
},
2121
config::{
22-
fragment::{self, Fragment, ValidationError},
22+
fragment::Fragment,
2323
merge::{Atomic, Merge},
2424
},
2525
deep_merger::ObjectOverrides,
2626
k8s_openapi::{
2727
api::core::v1::{EnvVar, PersistentVolumeClaim, Volume},
2828
apimachinery::pkg::api::resource::Quantity,
2929
},
30-
kube::{CustomResource, ResourceExt, runtime::reflector::ObjectRef},
30+
kube::{CustomResource, runtime::reflector::ObjectRef},
3131
kvp::Labels,
3232
product_logging::{self, spec::Logging},
3333
role_utils::{GenericRoleConfig, Role, RoleGroupRef},
@@ -107,18 +107,6 @@ pub type RestServerRoleType =
107107

108108
#[derive(Snafu, Debug)]
109109
pub enum Error {
110-
#[snafu(display("the HBase role [{role}] is missing from spec"))]
111-
MissingHbaseRole { role: String },
112-
113-
#[snafu(display("fragment validation failure"))]
114-
FragmentValidationFailure { source: ValidationError },
115-
116-
#[snafu(display("empty values for role-group are not permitted"))]
117-
EmptyRoleGroup,
118-
119-
#[snafu(display("role-group not found by name"))]
120-
RoleGroupNotFound,
121-
122110
#[snafu(display("failed to build listener volume"))]
123111
BuildListenerVolume {
124112
source: ListenerOperatorVolumeSourceBuilderError,
@@ -241,112 +229,6 @@ impl HasStatusCondition for v1alpha1::HbaseCluster {
241229
}
242230

243231
impl v1alpha1::HbaseCluster {
244-
/// Retrieve and merge resource configs for role and role groups
245-
/// Merges and validates the config for `role`/`role_group`.
246-
///
247-
/// The role-group config is merged on top of the role config on top of the
248-
/// operator defaults (most specific wins) and the result is validated.
249-
pub fn merged_config(
250-
&self,
251-
role: &HbaseRole,
252-
role_group: &str,
253-
hdfs_discovery_cm_name: &str,
254-
) -> Result<AnyServiceConfig, Error> {
255-
// Trivial values for role-groups are not allowed
256-
if role_group.is_empty() {
257-
return Err(Error::EmptyRoleGroup);
258-
}
259-
260-
match role {
261-
HbaseRole::Master => {
262-
let default_config = HbaseConfigFragment::default_config(
263-
role,
264-
&self.name_any(),
265-
hdfs_discovery_cm_name,
266-
);
267-
let role_obj = self.spec.masters.as_ref().context(MissingHbaseRoleSnafu {
268-
role: role.to_string(),
269-
})?;
270-
271-
let mut role_config = role_obj.config.config.clone();
272-
let mut role_group_config = role_obj
273-
.role_groups
274-
.get(role_group)
275-
.context(RoleGroupNotFoundSnafu)?
276-
.config
277-
.config
278-
.clone();
279-
280-
role_config.merge(&default_config);
281-
role_group_config.merge(&role_config);
282-
Ok(AnyServiceConfig::Master(
283-
fragment::validate(role_group_config)
284-
.context(FragmentValidationFailureSnafu)?,
285-
))
286-
}
287-
HbaseRole::RegionServer => {
288-
let default_config = RegionServerConfigFragment::default_config(
289-
role,
290-
&self.name_any(),
291-
hdfs_discovery_cm_name,
292-
);
293-
let role_obj =
294-
self.spec
295-
.region_servers
296-
.as_ref()
297-
.context(MissingHbaseRoleSnafu {
298-
role: role.to_string(),
299-
})?;
300-
301-
let mut role_config = role_obj.config.config.clone();
302-
let mut role_group_config = role_obj
303-
.role_groups
304-
.get(role_group)
305-
.context(RoleGroupNotFoundSnafu)?
306-
.config
307-
.config
308-
.clone();
309-
310-
role_config.merge(&default_config);
311-
role_group_config.merge(&role_config);
312-
Ok(AnyServiceConfig::RegionServer(
313-
fragment::validate(role_group_config)
314-
.context(FragmentValidationFailureSnafu)?,
315-
))
316-
}
317-
HbaseRole::RestServer => {
318-
let default_config = HbaseConfigFragment::default_config(
319-
role,
320-
&self.name_any(),
321-
hdfs_discovery_cm_name,
322-
);
323-
let role_obj = self
324-
.spec
325-
.rest_servers
326-
.as_ref()
327-
.context(MissingHbaseRoleSnafu {
328-
role: role.to_string(),
329-
})?;
330-
331-
let mut role_config = role_obj.config.config.clone();
332-
let mut role_group_config = role_obj
333-
.role_groups
334-
.get(role_group)
335-
.context(RoleGroupNotFoundSnafu)?
336-
.config
337-
.config
338-
.clone();
339-
340-
role_config.merge(&default_config);
341-
role_group_config.merge(&role_config);
342-
Ok(AnyServiceConfig::RestServer(
343-
fragment::validate(role_group_config)
344-
.context(FragmentValidationFailureSnafu)?,
345-
))
346-
}
347-
}
348-
}
349-
350232
/// Metadata about a server rolegroup
351233
pub fn server_rolegroup_ref(
352234
&self,
@@ -951,6 +833,110 @@ impl AnyServiceConfig {
951833
}
952834
}
953835

836+
#[cfg(test)]
837+
pub(crate) mod test_helpers {
838+
use stackable_operator::{
839+
config::{fragment::FromFragment, merge::Merge},
840+
kube::ResourceExt,
841+
role_utils::{GenericRoleConfig, Role},
842+
v2::{
843+
jvm_argument_overrides::JvmArgumentOverrides,
844+
role_utils::{JavaCommonConfig, with_validated_config},
845+
},
846+
};
847+
848+
use super::{
849+
AnyServiceConfig, HbaseConfig, HbaseConfigFragment, HbaseRole, RegionServerConfig,
850+
RegionServerConfigFragment, v1alpha1,
851+
};
852+
853+
/// Test helper: merge + validate a single role group via the production
854+
/// [`with_validated_config`] path (the same merge the controller runs), returning the
855+
/// role-specific [`AnyServiceConfig`] and the merged [`JvmArgumentOverrides`].
856+
pub(crate) fn merged_role_group_config(
857+
hbase: &v1alpha1::HbaseCluster,
858+
role: &HbaseRole,
859+
role_group: &str,
860+
hdfs_discovery_cm_name: &str,
861+
) -> (AnyServiceConfig, JvmArgumentOverrides) {
862+
match role {
863+
HbaseRole::Master => merge::<HbaseConfig, _>(
864+
hbase
865+
.spec
866+
.masters
867+
.as_ref()
868+
.expect("master role must be defined"),
869+
role_group,
870+
HbaseConfigFragment::default_config(
871+
role,
872+
&hbase.name_any(),
873+
hdfs_discovery_cm_name,
874+
),
875+
AnyServiceConfig::Master,
876+
),
877+
HbaseRole::RegionServer => merge::<RegionServerConfig, _>(
878+
hbase
879+
.spec
880+
.region_servers
881+
.as_ref()
882+
.expect("region server role must be defined"),
883+
role_group,
884+
RegionServerConfigFragment::default_config(
885+
role,
886+
&hbase.name_any(),
887+
hdfs_discovery_cm_name,
888+
),
889+
AnyServiceConfig::RegionServer,
890+
),
891+
HbaseRole::RestServer => merge::<HbaseConfig, _>(
892+
hbase
893+
.spec
894+
.rest_servers
895+
.as_ref()
896+
.expect("rest server role must be defined"),
897+
role_group,
898+
HbaseConfigFragment::default_config(
899+
role,
900+
&hbase.name_any(),
901+
hdfs_discovery_cm_name,
902+
),
903+
AnyServiceConfig::RestServer,
904+
),
905+
}
906+
}
907+
908+
fn merge<ValidatedConfig, Config>(
909+
role: &Role<Config, v1alpha1::HbaseConfigOverrides, GenericRoleConfig, JavaCommonConfig>,
910+
role_group: &str,
911+
default_config: Config,
912+
wrap: fn(ValidatedConfig) -> AnyServiceConfig,
913+
) -> (AnyServiceConfig, JvmArgumentOverrides)
914+
where
915+
Config: Clone + Merge,
916+
ValidatedConfig: FromFragment<Fragment = Config>,
917+
{
918+
let role_group = role
919+
.role_groups
920+
.get(role_group)
921+
.expect("role group must be defined");
922+
let validated = with_validated_config::<
923+
ValidatedConfig,
924+
JavaCommonConfig,
925+
Config,
926+
GenericRoleConfig,
927+
v1alpha1::HbaseConfigOverrides,
928+
>(role_group, role, &default_config)
929+
.expect("role group config should merge and validate");
930+
(
931+
wrap(validated.config.config),
932+
validated
933+
.config
934+
.product_specific_common_config
935+
.jvm_argument_overrides,
936+
)
937+
}
938+
}
939+
954940
#[cfg(test)]
955941
mod tests {
956942
use indoc::indoc;
@@ -1011,13 +997,12 @@ spec:
1011997
let hbase_role = HbaseRole::RegionServer;
1012998
let rolegroup = hbase.server_rolegroup_ref(hbase_role.to_string(), role_group_name);
1013999

1014-
let merged_config = hbase
1015-
.merged_config(
1016-
&hbase_role,
1017-
&rolegroup.role_group,
1018-
&hbase.spec.cluster_config.hdfs_config_map_name,
1019-
)
1020-
.unwrap();
1000+
let (merged_config, _) = super::test_helpers::merged_role_group_config(
1001+
&hbase,
1002+
&hbase_role,
1003+
&rolegroup.role_group,
1004+
&hbase.spec.cluster_config.hdfs_config_map_name,
1005+
);
10211006
if let AnyServiceConfig::RegionServer(config) = merged_config {
10221007
assert_eq!(run_before_shutdown, config.region_mover.run_before_shutdown);
10231008
assert_eq!(max_threads, config.region_mover.max_threads);

0 commit comments

Comments
 (0)