@@ -164,3 +164,102 @@ pub fn build(
164164 pod_disruption_budgets,
165165 } )
166166}
167+
168+ #[ cfg( test) ]
169+ mod tests {
170+ use stackable_operator:: { kube:: Resource , utils:: yaml_from_str_singleton_map} ;
171+
172+ use super :: build;
173+ use crate :: {
174+ controller:: {
175+ ValidatedCluster , test_support:: default_dereferenced, validate:: validate_cluster,
176+ } ,
177+ crd:: v1alpha1,
178+ } ;
179+
180+ /// A validated cluster with a `node`, `worker` and `beat` role (one `default` role group each).
181+ fn validated_cluster ( ) -> ValidatedCluster {
182+ let input = r#"
183+ apiVersion: superset.stackable.tech/v1alpha1
184+ kind: SupersetCluster
185+ metadata:
186+ name: simple-superset
187+ namespace: default
188+ spec:
189+ image:
190+ productVersion: 4.1.4
191+ clusterConfig:
192+ credentialsSecret: superset-admin-credentials
193+ metadataDatabase:
194+ postgresql:
195+ host: superset-postgresql
196+ database: superset
197+ credentialsSecretName: superset-postgresql-credentials
198+ nodes:
199+ roleGroups:
200+ default:
201+ replicas: 1
202+ workers:
203+ roleGroups:
204+ default:
205+ replicas: 1
206+ beat:
207+ roleGroups:
208+ default:
209+ replicas: 1
210+ "# ;
211+ let superset: v1alpha1:: SupersetCluster =
212+ yaml_from_str_singleton_map ( input) . expect ( "illegal test input" ) ;
213+ validate_cluster ( & superset, default_dereferenced ( ) , "test-repo" ) . expect ( "validated" )
214+ }
215+
216+ fn sorted_names ( resources : & [ impl Resource ] ) -> Vec < & str > {
217+ let mut names: Vec < & str > = resources
218+ . iter ( )
219+ . filter_map ( |resource| resource. meta ( ) . name . as_deref ( ) )
220+ . collect ( ) ;
221+ names. sort ( ) ;
222+ names
223+ }
224+
225+ /// The build step turns a validated cluster into the full set of Kubernetes resources: the
226+ /// `node` role becomes a StatefulSet, the `worker`/`beat` Celery roles become Deployments, and
227+ /// each role group additionally gets a ConfigMap and a metrics Service (plus a headless Service
228+ /// for the `node` role). Role-level Listeners and PDBs are emitted once per role.
229+ #[ test]
230+ fn build_produces_expected_resource_names ( ) {
231+ let cluster = validated_cluster ( ) ;
232+ let resources = build ( & cluster, "simple-superset-serviceaccount" ) . expect ( "build succeeds" ) ;
233+
234+ assert_eq ! (
235+ sorted_names( & resources. stateful_sets) ,
236+ [ "simple-superset-node-default" ]
237+ ) ;
238+ assert_eq ! (
239+ sorted_names( & resources. deployments) ,
240+ [
241+ "simple-superset-beat-default" ,
242+ "simple-superset-worker-default"
243+ ]
244+ ) ;
245+ assert_eq ! (
246+ sorted_names( & resources. config_maps) ,
247+ [
248+ "simple-superset-beat-default" ,
249+ "simple-superset-node-default" ,
250+ "simple-superset-worker-default" ,
251+ ]
252+ ) ;
253+ // Only the `node` role serves the web UI and gets a group Listener.
254+ assert_eq ! ( sorted_names( & resources. listeners) , [ "simple-superset-node" ] ) ;
255+ // A default PDB per role.
256+ assert_eq ! (
257+ sorted_names( & resources. pod_disruption_budgets) ,
258+ [
259+ "simple-superset-beat" ,
260+ "simple-superset-node" ,
261+ "simple-superset-worker"
262+ ]
263+ ) ;
264+ }
265+ }
0 commit comments