Skip to content

Commit 2732b53

Browse files
committed
refactor: introduce ValidatedMetastoreConfig; caluclate vector toml in build_config_map
1 parent 4e51f22 commit 2732b53

8 files changed

Lines changed: 98 additions & 75 deletions

File tree

rust/operator-binary/src/controller.rs

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ pub use stackable_operator::v2::types::operator::RoleGroupName;
1313
use stackable_operator::{
1414
cli::OperatorEnvironmentOptions,
1515
cluster_resources::ClusterResourceApplyStrategy,
16-
commons::{product_image_selection::ResolvedProductImage, rbac::build_rbac_resources},
16+
commons::{
17+
affinity::StackableAffinity,
18+
product_image_selection::ResolvedProductImage,
19+
rbac::build_rbac_resources,
20+
resources::{NoRuntimeLimits, Resources},
21+
},
1722
crd::{listener::v1alpha1::Listener, s3},
1823
database_connections::drivers::jdbc::JdbcDatabaseConnectionDetails,
1924
kube::{
@@ -169,22 +174,58 @@ impl ReconcilerError for Error {
169174
}
170175

171176
/// A validated, merged Hive metastore role-group config.
172-
///
173-
/// Built by [`validate::validate_cluster`] from the upstream
174-
/// [`stackable_operator::v2::role_utils::with_validated_config`] result. Holds only the
175-
/// fields the build steps consume; `cli_overrides` and the product-specific common config
176-
/// are intentionally not carried (hive does not use them).
177+
pub type HiveRoleGroupConfig = stackable_operator::v2::role_utils::RoleGroupConfig<
178+
ValidatedMetaStoreConfig,
179+
stackable_operator::v2::role_utils::JavaCommonConfig,
180+
v1alpha1::HiveConfigOverrides,
181+
>;
182+
183+
/// A validated Hive metastore config: the merged [`MetaStoreConfig`] with its raw `logging`
184+
/// replaced by the up-front [`ValidatedLogging`](validate::ValidatedLogging) (so an invalid
185+
/// custom log ConfigMap name or a missing Vector aggregator name fails reconciliation during
186+
/// validation).
177187
#[derive(Clone, Debug, PartialEq)]
178-
pub struct HiveRoleGroupConfig {
179-
pub replicas: u16,
180-
pub config: MetaStoreConfig,
181-
pub config_overrides: v1alpha1::HiveConfigOverrides,
182-
pub env_overrides: stackable_operator::v2::builder::pod::container::EnvVarSet,
183-
pub pod_overrides: stackable_operator::k8s_openapi::api::core::v1::PodTemplateSpec,
184-
pub jvm_argument_overrides:
185-
stackable_operator::v2::jvm_argument_overrides::JvmArgumentOverrides,
186-
/// Validated logging configuration (derived from `config.logging` during validation).
187-
pub logging: crate::controller::validate::ValidatedLogging,
188+
pub struct ValidatedMetaStoreConfig {
189+
pub affinity: StackableAffinity,
190+
pub graceful_shutdown_timeout: Option<Duration>,
191+
pub logging: validate::ValidatedLogging,
192+
pub resources: Resources<crate::crd::MetastoreStorageConfig, NoRuntimeLimits>,
193+
pub warehouse_dir: Option<String>,
194+
}
195+
196+
impl ValidatedMetaStoreConfig {
197+
/// Builds the validated config from the merged [`MetaStoreConfig`], swapping in the
198+
/// already-validated logging.
199+
fn from_merged(merged: MetaStoreConfig, logging: validate::ValidatedLogging) -> Self {
200+
Self {
201+
warehouse_dir: merged.warehouse_dir,
202+
resources: merged.resources,
203+
logging,
204+
affinity: merged.affinity,
205+
graceful_shutdown_timeout: merged.graceful_shutdown_timeout,
206+
}
207+
}
208+
209+
/// Wraps a merged [`MetaStoreConfig`] with trivial automatic logging, for builder tests
210+
/// that only exercise the non-logging parts of the config.
211+
#[cfg(test)]
212+
pub(crate) fn from_merged_for_test(merged: MetaStoreConfig) -> Self {
213+
use stackable_operator::{
214+
product_logging::spec::AutomaticContainerLogConfig,
215+
v2::product_logging::framework::ValidatedContainerLogConfigChoice,
216+
};
217+
218+
Self::from_merged(
219+
merged,
220+
validate::ValidatedLogging {
221+
hive_container: ValidatedContainerLogConfigChoice::Automatic(
222+
AutomaticContainerLogConfig::default(),
223+
),
224+
vector_container: None,
225+
enable_vector_agent: false,
226+
},
227+
)
228+
}
188229
}
189230

190231
/// The validated cluster: the typed, merged result of the validate step. Subsequent
@@ -480,14 +521,6 @@ pub async fn reconcile_hive(
480521

481522
for (hive_role, role_group_configs) in &validated_cluster.role_group_configs {
482523
for (role_group_name, rg) in role_group_configs {
483-
// The Vector agent config (`vector.yaml`) is a static, env-var-parameterized file
484-
// (mirroring the opensearch-operator). It is only added to the ConfigMap when the
485-
// Vector agent is enabled for this role group.
486-
let vector_config = rg
487-
.logging
488-
.enable_vector_agent
489-
.then(build::properties::product_logging::vector_config_file_content);
490-
491524
let rg_metrics_service =
492525
build_rolegroup_metrics_service(&validated_cluster, role_group_name);
493526

@@ -498,7 +531,6 @@ pub async fn reconcile_hive(
498531
&validated_cluster,
499532
role_group_name,
500533
rg,
501-
vector_config,
502534
)
503535
.with_context(|_| BuildRoleGroupConfigMapSnafu {
504536
role_group: role_group_name.clone(),

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use snafu::{ResultExt, Snafu};
22
use stackable_operator::builder::pod::PodBuilder;
33

4-
use crate::crd::MetaStoreConfig;
4+
use crate::controller::ValidatedMetaStoreConfig;
55

66
#[derive(Debug, Snafu)]
77
pub enum Error {
@@ -12,7 +12,7 @@ pub enum Error {
1212
}
1313

1414
pub fn add_graceful_shutdown_config(
15-
merged_config: &MetaStoreConfig,
15+
merged_config: &ValidatedMetaStoreConfig,
1616
pod_builder: &mut PodBuilder,
1717
) -> Result<(), Error> {
1818
// This must be always set by the merge mechanism, as we provide a default value,

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ use stackable_operator::memory::{BinaryMultiple, MemoryQuantity};
33

44
use super::{kerberos::STACKABLE_KERBEROS_DIR, properties::ConfigFileName};
55
use crate::{
6-
controller::{HiveRoleGroupConfig, ValidatedCluster},
6+
controller::{HiveRoleGroupConfig, ValidatedCluster, ValidatedMetaStoreConfig},
77
crd::{
8-
METRICS_PORT, MetaStoreConfig, STACKABLE_CONFIG_DIR, STACKABLE_TRUST_STORE,
9-
STACKABLE_TRUST_STORE_PASSWORD,
8+
METRICS_PORT, STACKABLE_CONFIG_DIR, STACKABLE_TRUST_STORE, STACKABLE_TRUST_STORE_PASSWORD,
109
},
1110
};
1211

@@ -44,7 +43,9 @@ fn construct_jvm_args(cluster: &ValidatedCluster, rg: &HiveRoleGroupConfig) -> V
4443

4544
// Apply the already-merged (role + role group) JVM argument overrides on top of the
4645
// operator-generated base arguments.
47-
rg.jvm_argument_overrides.apply_to(jvm_args)
46+
rg.product_specific_common_config
47+
.jvm_argument_overrides
48+
.apply_to(jvm_args)
4849
}
4950

5051
/// Arguments that go into `HADOOP_OPTS`, so *not* the heap settings (which you can get using
@@ -58,7 +59,9 @@ pub fn construct_non_heap_jvm_args(cluster: &ValidatedCluster, rg: &HiveRoleGrou
5859

5960
/// This will be put into `HADOOP_HEAPSIZE`, which is just the heap size in megabytes (*without* the `m`
6061
/// unit prepended).
61-
pub fn construct_hadoop_heapsize_env(merged_config: &MetaStoreConfig) -> Result<String, Error> {
62+
pub fn construct_hadoop_heapsize_env(
63+
merged_config: &ValidatedMetaStoreConfig,
64+
) -> Result<String, Error> {
6265
let heap_size_in_mb = (MemoryQuantity::try_from(
6366
merged_config
6467
.resources

rust/operator-binary/src/controller/build/properties/hive_site.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::collections::BTreeMap;
1515
use snafu::{ResultExt, Snafu};
1616
use stackable_operator::{crd::s3, k8s_openapi::api::core::v1::EnvVar};
1717

18-
use crate::{controller::ValidatedClusterConfig, crd::MetaStoreConfig};
18+
use crate::controller::{ValidatedClusterConfig, ValidatedMetaStoreConfig};
1919

2020
const DEFAULT_WAREHOUSE_DIR: &str = "/stackable/warehouse";
2121
const HIVE_METASTORE_PORT: &str = "hive.metastore.port";
@@ -51,7 +51,7 @@ type Result<T, E = Error> = std::result::Result<T, E>;
5151
pub fn build(
5252
cluster_config: &ValidatedClusterConfig,
5353
product_version: &str,
54-
merged_config: &MetaStoreConfig,
54+
merged_config: &ValidatedMetaStoreConfig,
5555
overrides: BTreeMap<String, String>,
5656
) -> Result<BTreeMap<String, String>> {
5757
let database_connection_details = &cluster_config.metadata_database_connection_details;
@@ -135,12 +135,14 @@ pub fn build(
135135
#[cfg(test)]
136136
mod tests {
137137
use super::*;
138-
use crate::controller::build::properties::test_support::derby_cluster_config;
138+
use crate::{
139+
controller::build::properties::test_support::derby_cluster_config, crd::MetaStoreConfig,
140+
};
139141

140142
#[test]
141143
fn defaults_present_for_minimal_derby_cluster() {
142144
let cluster_config = derby_cluster_config();
143-
let merged = MetaStoreConfig::default();
145+
let merged = ValidatedMetaStoreConfig::from_merged_for_test(MetaStoreConfig::default());
144146

145147
let data =
146148
build(&cluster_config, "4.0.0", &merged, BTreeMap::new()).expect("build hive-site");
@@ -162,10 +164,10 @@ mod tests {
162164
#[test]
163165
fn warehouse_dir_spec_overrides_default() {
164166
let cluster_config = derby_cluster_config();
165-
let merged = MetaStoreConfig {
167+
let merged = ValidatedMetaStoreConfig::from_merged_for_test(MetaStoreConfig {
166168
warehouse_dir: Some("/custom/warehouse".to_string()),
167169
..MetaStoreConfig::default()
168-
};
170+
});
169171

170172
let data =
171173
build(&cluster_config, "4.0.0", &merged, BTreeMap::new()).expect("build hive-site");
@@ -179,7 +181,7 @@ mod tests {
179181
#[test]
180182
fn user_override_wins_over_everything() {
181183
let cluster_config = derby_cluster_config();
182-
let merged = MetaStoreConfig::default();
184+
let merged = ValidatedMetaStoreConfig::from_merged_for_test(MetaStoreConfig::default());
183185
let overrides = [("hive.metastore.port".to_string(), "1234".to_string())]
184186
.into_iter()
185187
.collect();

rust/operator-binary/src/controller/build/properties/product_logging/mod.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,8 @@
33
44
use stackable_operator::{
55
memory::{BinaryMultiple, MemoryQuantity},
6-
product_logging::{
7-
self,
8-
spec::{
9-
AutomaticContainerLogConfig, ContainerLogConfig, ContainerLogConfigChoice, Logging,
10-
},
11-
},
12-
v2::product_logging::framework::STACKABLE_LOG_DIR,
6+
product_logging::{self, spec::AutomaticContainerLogConfig},
7+
v2::product_logging::framework::{STACKABLE_LOG_DIR, ValidatedContainerLogConfigChoice},
138
};
149

1510
use crate::crd::Container;
@@ -33,14 +28,12 @@ pub fn vector_config_file_content() -> String {
3328
/// Renders `log4j2.properties` for the Hive metastore container.
3429
///
3530
/// Returns `None` when the Hive container does not use the operator's automatic logging
36-
/// configuration (e.g. a custom log ConfigMap is referenced instead), in which case no
31+
/// configuration (i.e. a custom log ConfigMap is referenced instead), in which case no
3732
/// `log4j2.properties` should be added to the rolegroup `ConfigMap`.
38-
pub fn build_log4j2(logging: &Logging<Container>) -> Option<String> {
39-
match logging.containers.get(&Container::Hive) {
40-
Some(ContainerLogConfig {
41-
choice: Some(ContainerLogConfigChoice::Automatic(log_config)),
42-
}) => Some(log4j2_config(log_config)),
43-
_ => None,
33+
pub fn build_log4j2(hive_container: &ValidatedContainerLogConfigChoice) -> Option<String> {
34+
match hive_container {
35+
ValidatedContainerLogConfigChoice::Automatic(log_config) => Some(log4j2_config(log_config)),
36+
ValidatedContainerLogConfigChoice::Custom(_) => None,
4437
}
4538
}
4639

rust/operator-binary/src/controller/build/resource/config_map.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,10 @@ type Result<T, E = Error> = std::result::Result<T, E>;
3434

3535
/// The rolegroup [`ConfigMap`] configures the rolegroup based on the configuration given by the
3636
/// administrator.
37-
///
38-
/// `vector_config` is the Vector agent config (`vector.yaml`) built by the caller; it is `None`
39-
/// when the Vector agent is disabled.
4037
pub fn build_metastore_rolegroup_config_map(
4138
cluster: &ValidatedCluster,
4239
role_group_name: &RoleGroupName,
4340
rg: &HiveRoleGroupConfig,
44-
vector_config: Option<String>,
4541
) -> Result<ConfigMap> {
4642
// hive-site.xml
4743
let hive_site_overrides = rg.config_overrides.hive_site_xml.overrides.clone();
@@ -88,11 +84,16 @@ pub fn build_metastore_rolegroup_config_map(
8884
);
8985
}
9086

91-
if let Some(log4j2_properties) = product_logging::build_log4j2(&rg.config.logging) {
87+
if let Some(log4j2_properties) =
88+
product_logging::build_log4j2(&rg.config.logging.hive_container)
89+
{
9290
cm_builder.add_data(ConfigFileName::Log4j2.to_string(), log4j2_properties);
9391
}
94-
if let Some(vector_config) = vector_config {
95-
cm_builder.add_data(VECTOR_CONFIG_FILE, vector_config);
92+
if rg.config.logging.enable_vector_agent {
93+
cm_builder.add_data(
94+
VECTOR_CONFIG_FILE,
95+
product_logging::vector_config_file_content(),
96+
);
9697
}
9798

9899
cm_builder.build().with_context(|_| AssembleSnafu {

rust/operator-binary/src/controller/build/resource/statefulset.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ pub(crate) fn build_metastore_rolegroup_statefulset(
383383
// The Hive container's log config ConfigMap: either the operator-generated one (the rolegroup
384384
// ConfigMap, which carries the automatic `log4j2.properties`) or a user-provided custom
385385
// ConfigMap. This branches on the *validated* logging choice (see `ValidatedLogging`).
386-
let log_config_volume_config_map = match &rg.logging.hive_container {
386+
let log_config_volume_config_map = match &rg.config.logging.hive_container {
387387
ValidatedContainerLogConfigChoice::Custom(config_map_name) => config_map_name.to_string(),
388388
ValidatedContainerLogConfigChoice::Automatic(_) => {
389389
resource_names.role_group_config_map().to_string()
@@ -412,7 +412,7 @@ pub(crate) fn build_metastore_rolegroup_statefulset(
412412

413413
// N.B. the vector container should *follow* the hive container so that the hive one is the
414414
// default, is started first and can provide any dependencies that vector expects
415-
if let Some(vector_log_config) = &rg.logging.vector_container {
415+
if let Some(vector_log_config) = &rg.config.logging.vector_container {
416416
pod_builder.add_container(vector_container(
417417
&VECTOR_CONTAINER_NAME,
418418
resolved_product_image,

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

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use stackable_operator::{
2222
use crate::{
2323
controller::{
2424
HiveRoleGroupConfig, RoleGroupName, ValidatedCluster, ValidatedClusterConfig,
25-
ValidatedRoleConfig, build::kerberos::kerberos_config_properties,
25+
ValidatedMetaStoreConfig, ValidatedRoleConfig, build::kerberos::kerberos_config_properties,
2626
dereference::DereferencedObjects,
2727
},
2828
crd::{
@@ -273,12 +273,6 @@ pub fn validate_cluster(
273273
}
274274

275275
/// Merges and validates one role group into a [`HiveRoleGroupConfig`].
276-
///
277-
/// Uses the upstream [`with_validated_config`] (which merges the config fragment, the
278-
/// `configOverrides`, the `envOverrides`, the `podOverrides` and the product-specific
279-
/// [`JavaCommonConfig`] — including its `jvmArgumentOverrides`). The merged `envOverrides`
280-
/// (`HashMap`) are converted into an [`EnvVarSet`] here so invalid names fail validation
281-
/// early (the opensearch-operator pattern).
282276
fn validate_role_group_config(
283277
role_group_name: &RoleGroupName,
284278
role_group: &crate::crd::HiveRoleGroupType,
@@ -314,15 +308,13 @@ fn validate_role_group_config(
314308

315309
Ok(HiveRoleGroupConfig {
316310
replicas: merged.replicas.unwrap_or(1),
317-
config: merged.config.config,
311+
config: ValidatedMetaStoreConfig::from_merged(merged.config.config, logging),
318312
config_overrides: merged.config.config_overrides,
319313
env_overrides,
314+
// Hive does not use CLI overrides; the field is carried (and merged upstream) but unused.
315+
cli_overrides: merged.config.cli_overrides,
320316
pod_overrides: merged.config.pod_overrides,
321-
jvm_argument_overrides: merged
322-
.config
323-
.product_specific_common_config
324-
.jvm_argument_overrides,
325-
logging,
317+
product_specific_common_config: merged.config.product_specific_common_config,
326318
})
327319
}
328320

0 commit comments

Comments
 (0)