@@ -22,7 +22,7 @@ use stackable_operator::{
2222 product_logging:: framework:: {
2323 VectorContainerLogConfig , validate_logging_configuration_for_container,
2424 } ,
25- role_utils:: JavaCommonConfig ,
25+ role_utils:: { self , JavaCommonConfig } ,
2626 types:: {
2727 kubernetes:: { ConfigMapName , ListenerClassName , NamespaceName , Uid } ,
2828 operator:: {
@@ -118,6 +118,10 @@ fn validate_logging(
118118
119119type Result < T , E = Error > = std:: result:: Result < T , E > ;
120120
121+ stackable_operator:: constant!(
122+ DEFAULT_SPARK_CONNECT_ROLE_GROUP : RoleGroupName = DEFAULT_SPARK_CONNECT_GROUP_NAME
123+ ) ;
124+
121125/// Validated logging configuration for the (optional) Vector container.
122126///
123127/// Produced up-front by [`validate_logging`] so that an
@@ -134,6 +138,7 @@ pub struct ValidatedSparkConnectServer {
134138 pub name : ClusterName ,
135139 pub namespace : NamespaceName ,
136140 pub uid : Uid ,
141+ pub product_version : ProductVersion ,
137142 pub resolved_product_image : ResolvedProductImage ,
138143 pub cluster_config : ValidatedClusterConfig ,
139144 pub role_config : ValidatedRoleConfig ,
@@ -167,41 +172,56 @@ pub struct ValidatedRoleConfig {
167172}
168173
169174impl ValidatedSparkConnectServer {
175+ /// Recommended labels for a resource that is not tied to a concrete [`SparkConnectRole`]
176+ /// (e.g. the cluster-shared RBAC resources), using a free-form role/role-group label value.
177+ pub fn recommended_labels_for (
178+ & self ,
179+ role_name : & RoleName ,
180+ role_group_name : & RoleGroupName ,
181+ ) -> Labels {
182+ self . recommended_labels_with ( & self . product_version , role_name, role_group_name)
183+ }
184+
170185 /// Recommended labels for a resource of the given role.
171- pub ( crate ) fn recommended_labels ( & self , role : SparkConnectRole ) -> Labels {
172- // `app_version_label_value` is constructed to be a valid label value, so it is also a
173- // valid `ProductVersion`.
174- let product_version =
175- ProductVersion :: from_str ( & self . resolved_product_image . app_version_label_value )
176- . expect ( "the app version label value is a valid product version" ) ;
177- let role_group = RoleGroupName :: from_str ( DEFAULT_SPARK_CONNECT_GROUP_NAME )
178- . expect ( "DEFAULT_SPARK_CONNECT_GROUP_NAME is a valid role group name" ) ;
186+ pub fn recommended_labels ( & self , role : SparkConnectRole ) -> Labels {
187+ self . recommended_labels_for ( & role_name ( role) , & DEFAULT_SPARK_CONNECT_ROLE_GROUP )
188+ }
189+
190+ fn recommended_labels_with (
191+ & self ,
192+ product_version : & ProductVersion ,
193+ role_name : & RoleName ,
194+ role_group_name : & RoleGroupName ,
195+ ) -> Labels {
179196 recommended_labels (
180197 self ,
181198 & product_name ( ) ,
182- & product_version,
199+ product_version,
183200 & operator_name ( ) ,
184201 & controller_name ( ) ,
185- & role_name ( role ) ,
186- & role_group ,
202+ role_name,
203+ role_group_name ,
187204 )
188205 }
189206
190207 /// Selector labels matching the pods of the given role.
191- pub ( crate ) fn role_selector ( & self , role : SparkConnectRole ) -> Labels {
208+ pub fn role_selector ( & self , role : SparkConnectRole ) -> Labels {
192209 role_selector ( self , & product_name ( ) , & role_name ( role) )
193210 }
194211
195212 /// Selector labels matching the pods of the given role's (single) role group.
196- pub ( crate ) fn role_group_selector ( & self , role : SparkConnectRole ) -> Labels {
197- let role_group = RoleGroupName :: from_str ( DEFAULT_SPARK_CONNECT_GROUP_NAME )
198- . expect ( "DEFAULT_SPARK_CONNECT_GROUP_NAME is a valid role group name" ) ;
199- role_group_selector ( self , & product_name ( ) , & role_name ( role) , & role_group)
213+ pub fn role_group_selector ( & self , role : SparkConnectRole ) -> Labels {
214+ role_group_selector (
215+ self ,
216+ & product_name ( ) ,
217+ & role_name ( role) ,
218+ & DEFAULT_SPARK_CONNECT_ROLE_GROUP ,
219+ )
200220 }
201221
202222 /// Object metadata for a child resource named `name`, owned by this SparkConnectServer and
203223 /// carrying the recommended labels for the given role.
204- pub ( crate ) fn object_meta (
224+ pub fn object_meta (
205225 & self ,
206226 name : impl Into < String > ,
207227 role : SparkConnectRole ,
@@ -214,20 +234,29 @@ impl ValidatedSparkConnectServer {
214234 . with_labels ( self . recommended_labels ( role) ) ;
215235 builder
216236 }
237+
238+ /// Type-safe names for the per-cluster RBAC resources: the ServiceAccount,
239+ /// its (namespaced) RoleBinding, and the operator-deployed ClusterRole it binds.
240+ pub fn rbac_resource_names ( & self ) -> role_utils:: ResourceNames {
241+ role_utils:: ResourceNames {
242+ cluster_name : self . name . clone ( ) ,
243+ product_name : product_name ( ) ,
244+ }
245+ }
217246}
218247
219248/// The product name (`spark-connect`) as a type-safe label value.
220- pub ( crate ) fn product_name ( ) -> ProductName {
249+ pub fn product_name ( ) -> ProductName {
221250 ProductName :: from_str ( CONNECT_APP_NAME ) . expect ( "CONNECT_APP_NAME is a valid product name" )
222251}
223252
224253/// The operator name as a type-safe label value.
225- pub ( crate ) fn operator_name ( ) -> OperatorName {
254+ pub fn operator_name ( ) -> OperatorName {
226255 OperatorName :: from_str ( OPERATOR_NAME ) . expect ( "the operator name is a valid label value" )
227256}
228257
229258/// The controller name as a type-safe label value.
230- pub ( crate ) fn controller_name ( ) -> ControllerName {
259+ pub fn controller_name ( ) -> ControllerName {
231260 ControllerName :: from_str ( CONNECT_CONTROLLER_NAME )
232261 . expect ( "the controller name is a valid label value" )
233262}
@@ -304,6 +333,9 @@ pub fn validate(
304333 )
305334 . context ( ResolveProductImageSnafu ) ?;
306335
336+ let product_version = ProductVersion :: from_str ( & resolved_product_image. app_version_label_value )
337+ . expect ( "the app version label value is a valid product version" ) ;
338+
307339 let server_config = scs. server_config ( ) . context ( ServerConfigSnafu ) ?;
308340 let executor_config = scs. executor_config ( ) . context ( ExecutorConfigSnafu ) ?;
309341
@@ -350,6 +382,7 @@ pub fn validate(
350382 name,
351383 namespace,
352384 uid,
385+ product_version,
353386 resolved_product_image,
354387 cluster_config : ValidatedClusterConfig {
355388 resolved_s3 : dereferenced. resolved_s3 ,
0 commit comments