@@ -5,6 +5,13 @@ use stackable_operator::{
55 builder:: { self } ,
66 cluster_resources:: ClusterResourceApplyStrategy ,
77 commons:: rbac:: build_rbac_resources,
8+ crd:: listener,
9+ k8s_openapi:: api:: {
10+ apps:: v1:: StatefulSet ,
11+ core:: v1:: { ConfigMap , Service , ServiceAccount } ,
12+ policy:: v1:: PodDisruptionBudget ,
13+ rbac:: v1:: RoleBinding ,
14+ } ,
815 kube:: {
916 core:: { DeserializeGuard , error_boundary} ,
1017 runtime:: controller:: Action ,
@@ -18,13 +25,9 @@ use strum::{EnumDiscriminants, IntoStaticStr};
1825use crate :: {
1926 Ctx ,
2027 crd:: {
21- constants:: { HISTORY_APP_NAME , HISTORY_ROLE_NAME , JVM_SECURITY_PROPERTIES_FILE } ,
28+ constants:: { HISTORY_APP_NAME , JVM_SECURITY_PROPERTIES_FILE } ,
2229 history:: v1alpha1,
2330 } ,
24- history:: controller:: build:: resource:: {
25- config_map:: build_config_map, listener:: build_group_listener, pdb:: build_pdb,
26- service:: build_rolegroup_metrics_service, statefulset:: build_stateful_set,
27- } ,
2831} ;
2932
3033pub mod build;
@@ -49,18 +52,8 @@ pub enum Error {
4952 name : String ,
5053 } ,
5154
52- #[ snafu( display( "failed to update the history server stateful set" ) ) ]
53- ApplyStatefulSet {
54- source : stackable_operator:: cluster_resources:: Error ,
55- } ,
56-
57- #[ snafu( display( "failed to update history server config map" ) ) ]
58- ApplyConfigMap {
59- source : stackable_operator:: cluster_resources:: Error ,
60- } ,
61-
62- #[ snafu( display( "failed to update history server metrics service" ) ) ]
63- ApplyMetricsService {
55+ #[ snafu( display( "failed to apply Kubernetes resource" ) ) ]
56+ ApplyResource {
6457 source : stackable_operator:: cluster_resources:: Error ,
6558 } ,
6659
@@ -94,11 +87,6 @@ pub enum Error {
9487 rolegroup : String ,
9588 } ,
9689
97- #[ snafu( display( "failed to apply PodDisruptionBudget" ) ) ]
98- ApplyPdb {
99- source : stackable_operator:: cluster_resources:: Error ,
100- } ,
101-
10290 #[ snafu( display( "failed to get required Labels" ) ) ]
10391 GetRequiredLabels {
10492 source :
@@ -123,11 +111,6 @@ pub enum Error {
123111 source : Box < error_boundary:: InvalidObject > ,
124112 } ,
125113
126- #[ snafu( display( "failed to apply group listener" ) ) ]
127- ApplyGroupListener {
128- source : stackable_operator:: cluster_resources:: Error ,
129- } ,
130-
131114 #[ snafu( display( "failed to serialize Spark default properties" ) ) ]
132115 InvalidSparkDefaults { source : PropertiesWriterError } ,
133116}
@@ -137,7 +120,22 @@ impl ReconcilerError for Error {
137120 ErrorDiscriminants :: from ( self ) . into ( )
138121 }
139122}
140- /// Updates the status of the SparkApplication that started the pod.
123+
124+ /// Every Kubernetes resource produced by the build step for a SparkHistoryServer.
125+ ///
126+ /// Built without a Kubernetes client: all references are already dereferenced and validated by
127+ /// this point, so the only errors possible during assembly are resource-construction failures.
128+ pub struct SparkHistoryResources {
129+ pub service_account : ServiceAccount ,
130+ pub role_binding : RoleBinding ,
131+ /// One ConfigMap, metrics Service and StatefulSet per role group.
132+ pub config_maps : Vec < ConfigMap > ,
133+ pub metrics_services : Vec < Service > ,
134+ pub stateful_sets : Vec < StatefulSet > ,
135+ pub listener : listener:: v1alpha1:: Listener ,
136+ pub pod_disruption_budget : Option < PodDisruptionBudget > ,
137+ }
138+
141139pub async fn reconcile (
142140 shs : Arc < DeserializeGuard < v1alpha1:: SparkHistoryServer > > ,
143141 ctx : Arc < Ctx > ,
@@ -170,9 +168,9 @@ pub async fn reconcile(
170168 & shs. spec . object_overrides ,
171169 ) ;
172170
173- let log_dir = & validated . cluster_config . log_dir ;
174-
175- // Use a dedicated service account for history server pods .
171+ // Use a dedicated service account for history server pods. Building the RBAC resources needs
172+ // the cluster-resource labels, so it stays in the reconcile step; the built objects (whose
173+ // names are deterministic) are handed to the client-free build step .
176174 let ( service_account, role_binding) = build_rbac_resources (
177175 shs,
178176 HISTORY_APP_NAME ,
@@ -181,52 +179,47 @@ pub async fn reconcile(
181179 . context ( GetRequiredLabelsSnafu ) ?,
182180 )
183181 . context ( BuildRbacResourcesSnafu ) ?;
184- let service_account = cluster_resources
185- . add ( client, service_account)
182+
183+ let resources = build:: build ( & validated, service_account, role_binding) ?;
184+
185+ // Apply order: ServiceAccount and RoleBinding first, then the ConfigMaps, metrics Services,
186+ // Listener and PodDisruptionBudget, and finally the StatefulSets (they mount the ConfigMaps
187+ // and run under the SA, so those must exist first).
188+ cluster_resources
189+ . add ( client, resources. service_account )
186190 . await
187191 . context ( ApplyServiceAccountSnafu ) ?;
188192 cluster_resources
189- . add ( client, role_binding)
193+ . add ( client, resources . role_binding )
190194 . await
191195 . context ( ApplyRoleBindingSnafu ) ?;
192-
193- for ( role_group_name, rg) in & validated. role_groups {
194- let config_map = build_config_map ( & validated, role_group_name, rg) ?;
195-
196- let metrics_service = build_rolegroup_metrics_service ( & validated, role_group_name) ;
197-
198- let sts = build_stateful_set ( & validated, role_group_name, rg, log_dir, & service_account) ?;
199-
196+ for config_map in resources. config_maps {
200197 cluster_resources
201198 . add ( client, config_map)
202199 . await
203- . context ( ApplyConfigMapSnafu ) ?;
200+ . context ( ApplyResourceSnafu ) ?;
201+ }
202+ for metrics_service in resources. metrics_services {
204203 cluster_resources
205204 . add ( client, metrics_service)
206205 . await
207- . context ( ApplyMetricsServiceSnafu ) ?;
208- cluster_resources
209- . add ( client, sts)
210- . await
211- . context ( ApplyStatefulSetSnafu ) ?;
206+ . context ( ApplyResourceSnafu ) ?;
212207 }
213-
214- let rg_group_listener = build_group_listener (
215- & validated,
216- HISTORY_ROLE_NAME ,
217- validated. role_config . listener_class . clone ( ) ,
218- ) ;
219-
220208 cluster_resources
221- . add ( client, rg_group_listener )
209+ . add ( client, resources . listener )
222210 . await
223- . context ( ApplyGroupListenerSnafu ) ?;
224-
225- if let Some ( pdb) = build_pdb ( & validated. role_config . pdb , & validated) {
211+ . context ( ApplyResourceSnafu ) ?;
212+ if let Some ( pdb) = resources. pod_disruption_budget {
226213 cluster_resources
227214 . add ( client, pdb)
228215 . await
229- . context ( ApplyPdbSnafu ) ?;
216+ . context ( ApplyResourceSnafu ) ?;
217+ }
218+ for stateful_set in resources. stateful_sets {
219+ cluster_resources
220+ . add ( client, stateful_set)
221+ . await
222+ . context ( ApplyResourceSnafu ) ?;
230223 }
231224
232225 cluster_resources
0 commit comments