11//! Builds the rolegroup [`ConfigMap`] from a [`ValidatedCluster`].
22//!
3- //! The per-file "validated config" maps (runtime.properties / security.properties) are taken
4- //! from the [`DruidRoleGroupConfig`] precomputed in the validate step; product-config is no
5- //! longer involved.
3+ //! The per-file configs (runtime.properties / security.properties / jvm.config) are rendered here
4+ //! from the merged [`DruidRoleGroupConfig`] (config plus the merged config overrides); the
5+ //! recommended cluster-level runtime properties and the erased roles needed for `jvm.config` are
6+ //! carried on `ValidatedCluster`. Product-config is no longer involved.
67//!
78//! Metadata, owner reference and recommended labels are derived entirely from `ValidatedCluster`
89//! (which carries the validated name/namespace/uid and implements `Resource`).
910//!
10- //! The builder no longer reads the raw [`v1alpha1::DruidCluster`] at all: the extensions load
11- //! list, the metadata-database connection / storage type and the rendered `jvm.config` are all
12- //! precomputed on `ValidatedCluster` during the validate step.
11+ //! The builder does not read the raw [`v1alpha1::DruidCluster`] at all: everything it needs is
12+ //! carried on `ValidatedCluster` (resolved during the validate step).
1313
1414use std:: collections:: BTreeMap ;
1515
@@ -28,15 +28,19 @@ use stackable_operator::{
2828use crate :: {
2929 controller:: {
3030 DRUID_CONTROLLER_NAME ,
31- build:: properties:: {
32- ConfigFileName ,
33- logging:: { build_log4j2_config, build_vector_config} ,
31+ build:: {
32+ jvm:: construct_jvm_args,
33+ properties:: {
34+ ConfigFileName ,
35+ logging:: { build_log4j2_config, build_vector_config} ,
36+ runtime_properties, security_properties,
37+ } ,
3438 } ,
3539 validate:: { DruidRoleGroupConfig , ValidatedCluster } ,
3640 } ,
3741 crd:: {
38- DruidRole , build_recommended_labels , build_string_list , env_var_reference , file_reference ,
39- v1alpha1,
42+ DruidConfigOverrides , DruidRole , STACKABLE_TRUST_STORE , STACKABLE_TRUST_STORE_PASSWORD ,
43+ build_recommended_labels , build_string_list , env_var_reference , file_reference , v1alpha1,
4044 } ,
4145} ;
4246
@@ -87,10 +91,56 @@ pub enum Error {
8791 GenerateAuthenticationRuntimeSettings {
8892 source : crate :: authentication:: Error ,
8993 } ,
94+
95+ #[ snafu( display( "failed to derive Druid memory settings from resources" ) ) ]
96+ DeriveMemorySettings { source : crate :: crd:: resource:: Error } ,
97+
98+ #[ snafu( display( "failed to construct the jvm.config" ) ) ]
99+ GetJvmConfig {
100+ source : crate :: controller:: build:: jvm:: Error ,
101+ } ,
90102}
91103
92104type Result < T , E = Error > = std:: result:: Result < T , E > ;
93105
106+ const INDEXER_JAVA_OPTS : & str = "druid.indexer.runner.javaOptsArray" ;
107+
108+ /// The `druid.indexer.runner.javaOptsArray` entry that must be present in *every* rendered file
109+ /// (runtime.properties and security.properties) for MiddleManagers.
110+ fn middlemanager_indexer_java_opts ( ) -> ( String , String ) {
111+ (
112+ INDEXER_JAVA_OPTS . to_string ( ) ,
113+ build_string_list ( & [
114+ format ! ( "-Djavax.net.ssl.trustStore={STACKABLE_TRUST_STORE}" ) ,
115+ format ! ( "-Djavax.net.ssl.trustStorePassword={STACKABLE_TRUST_STORE_PASSWORD}" ) ,
116+ "-Djavax.net.ssl.trustStoreType=pkcs12" . to_owned ( ) ,
117+ ] ) ,
118+ )
119+ }
120+
121+ /// Returns the user-supplied key/value overrides for the given config file from a
122+ /// [`DruidConfigOverrides`].
123+ ///
124+ /// The CRD override map allows a value-less key (`someKey:` / null in YAML), modelled as
125+ /// `Option<String>`. We flatten `None` to an empty string here, matching how the Java properties
126+ /// writer rendered a missing value (`key=`), so the rest of the pipeline can work with plain
127+ /// `String` values.
128+ fn key_value_overrides (
129+ overrides : & DruidConfigOverrides ,
130+ file : ConfigFileName ,
131+ ) -> BTreeMap < String , String > {
132+ let raw = match file {
133+ ConfigFileName :: RuntimeProperties => overrides. runtime_properties . overrides . clone ( ) ,
134+ ConfigFileName :: SecurityProperties => overrides. security_properties . overrides . clone ( ) ,
135+ // log4j2.properties is rendered by the logging framework, and jvm.config is rendered from
136+ // JVM argument overrides; neither is assembled from key/value overrides here.
137+ ConfigFileName :: Log4j2Properties | ConfigFileName :: JvmConfig => BTreeMap :: new ( ) ,
138+ } ;
139+ raw. into_iter ( )
140+ . map ( |( k, v) | ( k, v. unwrap_or_default ( ) ) )
141+ . collect ( )
142+ }
143+
94144/// The rolegroup [`ConfigMap`] configures the rolegroup based on the configuration given by the administrator
95145pub fn build_rolegroup_config_map (
96146 cluster : & ValidatedCluster ,
@@ -117,7 +167,7 @@ pub fn build_rolegroup_config_map(
117167 // This has to be done here since there is no other suitable place for it.
118168 // Previously such properties were added in the compute_files() function,
119169 // but that code path is now incompatible with the design of fragment merging.
120- rg. merged_config
170+ rg. config
121171 . resources
122172 . update_druid_config_file ( & mut conf)
123173 . context ( UpdateDruidConfigFromResourcesSnafu ) ?;
@@ -217,8 +267,22 @@ pub fn build_rolegroup_config_map(
217267 ) ;
218268 } ;
219269
220- // extend the config to respect the precomputed defaults and overrides
221- conf. extend ( rg. runtime_config . clone ( ) ) ;
270+ // Role/rolegroup runtime.properties: the recommended cluster-config-derived properties,
271+ // the MiddleManager indexer opts, the per-role defaults and finally the user overrides
272+ // (each layer wins over the previous, and over the cluster-level properties above).
273+ conf. extend ( runtime_properties:: cluster_runtime_properties (
274+ & cluster_config. deep_storage ,
275+ cluster_config. opa_connection_string . is_some ( ) ,
276+ ) ) ;
277+ if * role == DruidRole :: MiddleManager {
278+ let ( k, v) = middlemanager_indexer_java_opts ( ) ;
279+ conf. insert ( k, v) ;
280+ }
281+ conf. extend ( runtime_properties:: defaults ( role) ) ;
282+ conf. extend ( key_value_overrides (
283+ & rg. config_overrides ,
284+ ConfigFileName :: RuntimeProperties ,
285+ ) ) ;
222286
223287 let runtime_properties =
224288 to_java_properties_string ( conf. iter ( ) ) . context ( SerializeRuntimePropertiesSnafu ) ?;
@@ -229,14 +293,37 @@ pub fn build_rolegroup_config_map(
229293 }
230294
231295 // ----- jvm.config -----
232- // Precomputed during validation; see `DruidRoleGroupConfig::jvm_config`.
233- cm_conf_data. insert ( ConfigFileName :: JvmConfig . to_string ( ) , rg. jvm_config . clone ( ) ) ;
296+ {
297+ let ( heap, direct) = rg
298+ . config
299+ . resources
300+ . get_memory_sizes ( role)
301+ . context ( DeriveMemorySettingsSnafu ) ?;
302+ let jvm_config = construct_jvm_args (
303+ role,
304+ cluster. get_role ( role) ,
305+ & rolegroup. role_group ,
306+ heap,
307+ direct,
308+ )
309+ . context ( GetJvmConfigSnafu ) ?;
310+ cm_conf_data. insert ( ConfigFileName :: JvmConfig . to_string ( ) , jvm_config) ;
311+ }
234312
235313 // ----- security.properties -----
236314 {
315+ let mut security_config: BTreeMap < String , String > = BTreeMap :: new ( ) ;
316+ if * role == DruidRole :: MiddleManager {
317+ let ( k, v) = middlemanager_indexer_java_opts ( ) ;
318+ security_config. insert ( k, v) ;
319+ }
320+ let security_overrides =
321+ key_value_overrides ( & rg. config_overrides , ConfigFileName :: SecurityProperties ) ;
322+ security_config. extend ( security_properties:: build ( & security_overrides) ) ;
323+
237324 cm_conf_data. insert (
238325 ConfigFileName :: SecurityProperties . to_string ( ) ,
239- to_java_properties_string ( rg . security_config . iter ( ) ) . with_context ( |_| {
326+ to_java_properties_string ( security_config. iter ( ) ) . with_context ( |_| {
240327 JvmSecurityPropertiesSnafu {
241328 rolegroup : rolegroup. role_group . clone ( ) ,
242329 }
@@ -265,11 +352,11 @@ pub fn build_rolegroup_config_map(
265352 config_map_builder. add_data ( filename, file_content) ;
266353 }
267354
268- if let Some ( log4j2_config) = build_log4j2_config ( & rg. merged_config . logging ) {
355+ if let Some ( log4j2_config) = build_log4j2_config ( & rg. config . logging ) {
269356 config_map_builder. add_data ( ConfigFileName :: Log4j2Properties . to_string ( ) , log4j2_config) ;
270357 }
271358
272- if let Some ( vector_config) = build_vector_config ( rolegroup, & rg. merged_config . logging ) {
359+ if let Some ( vector_config) = build_vector_config ( rolegroup, & rg. config . logging ) {
273360 config_map_builder. add_data ( VECTOR_CONFIG_FILE , vector_config) ;
274361 }
275362
0 commit comments