@@ -12,6 +12,7 @@ use crate::controller::{
1212 config_map:: build_rolegroup_config_map,
1313 daemonset:: build_server_rolegroup_daemonset,
1414 discovery:: build_discovery_config_map,
15+ rbac:: { build_role_binding, build_service_account} ,
1516 service:: {
1617 build_rolegroup_headless_service, build_rolegroup_metrics_service,
1718 build_server_role_service,
@@ -51,7 +52,6 @@ pub enum Error {
5152/// Kubernetes cluster domain used in the discovery URL and the sidecar environment.
5253pub fn build (
5354 cluster : & ValidatedCluster ,
54- service_account_name : & str ,
5555 opa_bundle_builder_image : & str ,
5656 user_info_fetcher_image : & str ,
5757 cluster_info : & KubernetesClusterInfo ,
@@ -81,7 +81,6 @@ pub fn build(
8181 role_group,
8282 opa_bundle_builder_image,
8383 user_info_fetcher_image,
84- service_account_name,
8584 cluster_info,
8685 )
8786 . context ( DaemonSetSnafu {
@@ -98,6 +97,8 @@ pub fn build(
9897 daemon_sets,
9998 services,
10099 config_maps,
100+ service_accounts : vec ! [ build_service_account( cluster) ] ,
101+ role_bindings : vec ! [ build_role_binding( cluster) ] ,
101102 } )
102103}
103104
@@ -115,6 +116,8 @@ stackable_operator::constant!(pub(crate) PLACEHOLDER_DISCOVERY_ROLE_GROUP: RoleG
115116
116117#[ cfg( test) ]
117118mod tests {
119+ use std:: collections:: BTreeMap ;
120+
118121 use serde_json:: json;
119122 use stackable_operator:: {
120123 commons:: networking:: DomainName , kube:: Resource , utils:: cluster_info:: KubernetesClusterInfo ,
@@ -152,7 +155,6 @@ mod tests {
152155 fn build_produces_expected_resource_names ( ) {
153156 let resources = build (
154157 & cluster ( ) ,
155- "test-opa-serviceaccount" ,
156158 "bundle-builder-image" ,
157159 "user-info-fetcher-image" ,
158160 & cluster_info ( ) ,
@@ -179,4 +181,58 @@ mod tests {
179181 [ "test-opa" , "test-opa-server-default" ]
180182 ) ;
181183 }
184+
185+ /// Locks the RBAC resource names, the roleRef, and the recommended label set against
186+ /// accidental drift. The fixture's cluster name deliberately differs from the product name so
187+ /// that swapped `name`/`instance` label values cannot pass unnoticed.
188+ #[ test]
189+ fn build_produces_rbac ( ) {
190+ let resources = build (
191+ & cluster ( ) ,
192+ "bundle-builder-image" ,
193+ "user-info-fetcher-image" ,
194+ & cluster_info ( ) ,
195+ )
196+ . expect ( "build succeeds" ) ;
197+
198+ assert_eq ! (
199+ sorted_names( & resources. service_accounts) ,
200+ [ "test-opa-serviceaccount" ]
201+ ) ;
202+ assert_eq ! (
203+ sorted_names( & resources. role_bindings) ,
204+ [ "test-opa-rolebinding" ]
205+ ) ;
206+
207+ let expected_labels = BTreeMap :: from (
208+ [
209+ ( "app.kubernetes.io/component" , "none" ) ,
210+ ( "app.kubernetes.io/instance" , "test-opa" ) ,
211+ (
212+ "app.kubernetes.io/managed-by" ,
213+ "opa.stackable.tech_opacluster" ,
214+ ) ,
215+ ( "app.kubernetes.io/name" , "opa" ) ,
216+ ( "app.kubernetes.io/role-group" , "none" ) ,
217+ ( "app.kubernetes.io/version" , "1.2.3-stackable0.0.0-dev" ) ,
218+ ( "stackable.tech/vendor" , "Stackable" ) ,
219+ ]
220+ . map ( |( key, value) | ( key. to_string ( ) , value. to_string ( ) ) ) ,
221+ ) ;
222+ let service_account = resources
223+ . service_accounts
224+ . first ( )
225+ . expect ( "a ServiceAccount is built" ) ;
226+ assert_eq ! (
227+ service_account. metadata. labels,
228+ Some ( expected_labels. clone( ) )
229+ ) ;
230+
231+ let role_binding = resources
232+ . role_bindings
233+ . first ( )
234+ . expect ( "a RoleBinding is built" ) ;
235+ assert_eq ! ( role_binding. metadata. labels, Some ( expected_labels) ) ;
236+ assert_eq ! ( role_binding. role_ref. name, "opa-clusterrole" ) ;
237+ }
182238}
0 commit comments