11//! Ensures that `Pod`s are configured and running for each [`v1alpha1::KafkaCluster`].
22
3- use std:: { collections:: BTreeMap , sync:: Arc } ;
3+ use std:: { borrow :: Cow , collections:: BTreeMap , sync:: Arc } ;
44
55use const_format:: concatcp;
66use snafu:: { ResultExt , Snafu } ;
@@ -11,7 +11,7 @@ use stackable_operator::{
1111 crd:: listener,
1212 kube:: {
1313 Resource ,
14- api:: DynamicObject ,
14+ api:: { DynamicObject , ObjectMeta } ,
1515 core:: { DeserializeGuard , error_boundary} ,
1616 runtime:: { controller:: Action , reflector:: ObjectRef } ,
1717 } ,
@@ -22,6 +22,10 @@ use stackable_operator::{
2222 compute_conditions, operations:: ClusterOperationsConditionBuilder ,
2323 statefulset:: StatefulSetConditionBuilder ,
2424 } ,
25+ v2:: types:: {
26+ kubernetes:: { NamespaceName , Uid } ,
27+ operator:: ClusterName ,
28+ } ,
2529} ;
2630use strum:: { EnumDiscriminants , IntoStaticStr } ;
2731
@@ -38,7 +42,6 @@ use crate::{
3842 security:: KafkaTlsSecurity ,
3943 v1alpha1,
4044 } ,
41- discovery:: { self , build_discovery_configmap} ,
4245 operations:: pdb:: add_pdbs,
4346 resource:: {
4447 listener:: build_broker_rolegroup_bootstrap_listener,
@@ -94,7 +97,7 @@ pub enum Error {
9497 } ,
9598
9699 #[ snafu( display( "failed to build discovery ConfigMap" ) ) ]
97- BuildDiscoveryConfig { source : discovery:: Error } ,
100+ BuildDiscoveryConfig { source : build :: discovery:: Error } ,
98101
99102 #[ snafu( display( "failed to apply discovery ConfigMap" ) ) ]
100103 ApplyDiscoveryConfig {
@@ -208,7 +211,17 @@ impl ReconcilerError for Error {
208211
209212/// The validated cluster. Carries everything the build steps need, resolved once
210213/// here so downstream code never re-derives it or touches the raw spec.
214+ ///
215+ /// The cluster identity (`name`, `namespace`, `uid`) is captured here so that owner
216+ /// references for child objects can be built straight from this struct (via its
217+ /// [`Resource`] impl) without threading the raw [`v1alpha1::KafkaCluster`] around.
218+ /// This mirrors the hive-/opensearch-operator's `ValidatedCluster`.
211219pub struct ValidatedKafkaCluster {
220+ /// `ObjectMeta` carrying `name`, `namespace` and `uid`, so this struct can act as the
221+ /// owner [`Resource`] for child objects.
222+ metadata : ObjectMeta ,
223+ pub name : ClusterName ,
224+ pub namespace : NamespaceName ,
212225 pub image : ResolvedProductImage ,
213226 pub kafka_security : KafkaTlsSecurity ,
214227 // DESIGN DECISION: the dereferenced authorization config is folded into the
@@ -222,6 +235,69 @@ pub struct ValidatedKafkaCluster {
222235 pub metadata_manager : MetadataManager ,
223236}
224237
238+ impl ValidatedKafkaCluster {
239+ #[ allow( clippy:: too_many_arguments) ]
240+ pub fn new (
241+ name : ClusterName ,
242+ namespace : NamespaceName ,
243+ uid : Uid ,
244+ image : ResolvedProductImage ,
245+ kafka_security : KafkaTlsSecurity ,
246+ authorization_config : Option < KafkaAuthorizationConfig > ,
247+ role_groups : BTreeMap < KafkaRole , BTreeMap < String , ValidatedRoleGroupConfig > > ,
248+ pod_descriptors : Vec < KafkaPodDescriptor > ,
249+ metadata_manager : MetadataManager ,
250+ ) -> Self {
251+ Self {
252+ metadata : ObjectMeta {
253+ name : Some ( name. to_string ( ) ) ,
254+ namespace : Some ( namespace. to_string ( ) ) ,
255+ uid : Some ( uid. to_string ( ) ) ,
256+ ..ObjectMeta :: default ( )
257+ } ,
258+ name,
259+ namespace,
260+ image,
261+ kafka_security,
262+ authorization_config,
263+ role_groups,
264+ pod_descriptors,
265+ metadata_manager,
266+ }
267+ }
268+ }
269+
270+ /// Lets [`ValidatedKafkaCluster`] act as the owner [`Resource`] for child objects, so owner
271+ /// references are built from it (via the captured `metadata`) rather than the raw CR.
272+ impl Resource for ValidatedKafkaCluster {
273+ type DynamicType = <v1alpha1:: KafkaCluster as Resource >:: DynamicType ;
274+ type Scope = <v1alpha1:: KafkaCluster as Resource >:: Scope ;
275+
276+ fn kind ( dt : & Self :: DynamicType ) -> Cow < ' _ , str > {
277+ v1alpha1:: KafkaCluster :: kind ( dt)
278+ }
279+
280+ fn group ( dt : & Self :: DynamicType ) -> Cow < ' _ , str > {
281+ v1alpha1:: KafkaCluster :: group ( dt)
282+ }
283+
284+ fn version ( dt : & Self :: DynamicType ) -> Cow < ' _ , str > {
285+ v1alpha1:: KafkaCluster :: version ( dt)
286+ }
287+
288+ fn plural ( dt : & Self :: DynamicType ) -> Cow < ' _ , str > {
289+ v1alpha1:: KafkaCluster :: plural ( dt)
290+ }
291+
292+ fn meta ( & self ) -> & ObjectMeta {
293+ & self . metadata
294+ }
295+
296+ fn meta_mut ( & mut self ) -> & mut ObjectMeta {
297+ & mut self . metadata
298+ }
299+ }
300+
225301pub struct ValidatedRoleGroupConfig {
226302 pub merged_config : AnyConfig ,
227303 // DESIGN DECISION: overrides are resolved into flat maps HERE rather than stored
@@ -265,7 +341,7 @@ pub async fn reconcile_kafka(
265341 APP_NAME ,
266342 OPERATOR_NAME ,
267343 KAFKA_CONTROLLER_NAME ,
268- & kafka . object_ref ( & ( ) ) ,
344+ & validated_cluster . object_ref ( & ( ) ) ,
269345 ClusterResourceApplyStrategy :: from ( & kafka. spec . cluster_operation ) ,
270346 & kafka. spec . object_overrides ,
271347 )
@@ -306,16 +382,19 @@ pub async fn reconcile_kafka(
306382 let rolegroup_ref = kafka. rolegroup_ref ( kafka_role, rolegroup_name) ;
307383
308384 let rg_headless_service = build_rolegroup_headless_service (
309- kafka ,
385+ & validated_cluster ,
310386 & validated_cluster. image ,
311387 & rolegroup_ref,
312388 & validated_cluster. kafka_security ,
313389 )
314390 . context ( BuildServiceSnafu ) ?;
315391
316- let rg_metrics_service =
317- build_rolegroup_metrics_service ( kafka, & validated_cluster. image , & rolegroup_ref)
318- . context ( BuildServiceSnafu ) ?;
392+ let rg_metrics_service = build_rolegroup_metrics_service (
393+ & validated_cluster,
394+ & validated_cluster. image ,
395+ & rolegroup_ref,
396+ )
397+ . context ( BuildServiceSnafu ) ?;
319398
320399 let kafka_listeners = get_kafka_listener_config (
321400 kafka,
@@ -416,8 +495,9 @@ pub async fn reconcile_kafka(
416495 }
417496 }
418497
419- let discovery_cm = build_discovery_configmap ( kafka, validated_cluster, & bootstrap_listeners)
420- . context ( BuildDiscoveryConfigSnafu ) ?;
498+ let discovery_cm =
499+ build:: discovery:: build_discovery_configmap ( & validated_cluster, & bootstrap_listeners)
500+ . context ( BuildDiscoveryConfigSnafu ) ?;
421501
422502 cluster_resources
423503 . add ( client, discovery_cm)
0 commit comments