44
55use std:: str:: FromStr ;
66
7- use snafu:: { OptionExt , ResultExt , Snafu } ;
8- use stackable_operator:: v2:: types:: { common:: Port , operator:: RoleGroupName } ;
7+ use snafu:: { ResultExt , Snafu } ;
8+ use stackable_operator:: {
9+ builder:: meta:: ObjectMetaBuilder ,
10+ v2:: {
11+ builder:: meta:: ownerreference_from_resource,
12+ types:: { common:: Port , operator:: RoleGroupName } ,
13+ } ,
14+ } ;
915
1016use crate :: {
1117 controller:: {
@@ -14,6 +20,7 @@ use crate::{
1420 config_map:: build_rolegroup_config_map,
1521 listener:: { build_group_listener, group_listener_name} ,
1622 pdb:: build_pdb,
23+ rbac:: { build_role_binding, build_service_account} ,
1724 service:: { build_rolegroup_headless_service, build_rolegroup_metrics_service} ,
1825 statefulset:: build_node_rolegroup_statefulset,
1926 } ,
@@ -45,9 +52,6 @@ pub const NIFI_PYTHON_WORKING_DIRECTORY: &str = "/nifi-python-working-directory"
4552
4653#[ derive( Snafu , Debug ) ]
4754pub enum Error {
48- #[ snafu( display( "NifiCluster has no nodes role defined" ) ) ]
49- NoNodesDefined ,
50-
5155 #[ snafu( display( "failed to build ConfigMap for role group {role_group}" ) ) ]
5256 ConfigMap {
5357 source : resource:: config_map:: Error ,
@@ -66,13 +70,7 @@ pub enum Error {
6670/// Does not need a Kubernetes client: every reference to another Kubernetes resource is already
6771/// dereferenced and validated by this point, so the errors returned here are resource-assembly
6872/// failures only.
69- ///
70- /// `service_account_name` is the name of the RBAC `ServiceAccount` the role-group Pods run under
71- /// (RBAC resources are built and applied separately, in the reconcile step).
72- pub fn build (
73- cluster : & ValidatedCluster ,
74- service_account_name : & str ,
75- ) -> Result < KubernetesResources , Error > {
73+ pub fn build ( cluster : & ValidatedCluster ) -> Result < KubernetesResources , Error > {
7674 let mut stateful_sets = vec ! [ ] ;
7775 let mut services = vec ! [ ] ;
7876 let mut listeners = vec ! [ ] ;
@@ -84,7 +82,7 @@ pub fn build(
8482 let node_role_group_configs = cluster
8583 . role_group_configs
8684 . get ( & nifi_role)
87- . context ( NoNodesDefinedSnafu ) ? ;
85+ . expect ( "the nodes role is required by the CRD and validate always inserts it" ) ;
8886
8987 // Role-level resources (one per role): the PodDisruptionBudget and the group Listener.
9088 let role_config = & cluster. role_config ;
@@ -109,16 +107,10 @@ pub fn build(
109107
110108 let effective_replicas = rg. replicas . map ( i32:: from) ;
111109 stateful_sets. push (
112- build_node_rolegroup_statefulset (
113- cluster,
114- role_group_name,
115- rg,
116- effective_replicas,
117- service_account_name,
118- )
119- . context ( StatefulSetSnafu {
120- role_group : role_group_name. clone ( ) ,
121- } ) ?,
110+ build_node_rolegroup_statefulset ( cluster, role_group_name, rg, effective_replicas)
111+ . context ( StatefulSetSnafu {
112+ role_group : role_group_name. clone ( ) ,
113+ } ) ?,
122114 ) ;
123115 }
124116
@@ -128,9 +120,33 @@ pub fn build(
128120 listeners,
129121 config_maps,
130122 pod_disruption_budgets,
123+ service_accounts : vec ! [ build_service_account( cluster) ] ,
124+ role_bindings : vec ! [ build_role_binding( cluster) ] ,
131125 } )
132126}
133127
128+ /// Returns an [`ObjectMetaBuilder`] pre-filled with the namespace, an owner reference back to
129+ /// the cluster, and the recommended labels for a resource named `name` in `role_group_name`.
130+ ///
131+ /// Consolidates the metadata chain repeated by the child-resource builders. Call sites that
132+ /// need extra labels/annotations chain them onto the returned builder. Role-level resources
133+ /// (e.g. the per-role [`Listener`](stackable_operator::crd::listener::v1alpha1::Listener)) pass
134+ /// the placeholder role-group `none`, preserving the historical
135+ /// `app.kubernetes.io/role-group: none` label.
136+ pub ( crate ) fn object_meta (
137+ cluster : & ValidatedCluster ,
138+ name : impl Into < String > ,
139+ role_group_name : & RoleGroupName ,
140+ ) -> ObjectMetaBuilder {
141+ let mut builder = ObjectMetaBuilder :: new ( ) ;
142+ builder
143+ . name_and_namespace ( cluster)
144+ . name ( name)
145+ . ownerreference ( ownerreference_from_resource ( cluster, None , Some ( true ) ) )
146+ . with_labels ( cluster. recommended_labels ( role_group_name) ) ;
147+ builder
148+ }
149+
134150#[ cfg( test) ]
135151mod tests {
136152 use stackable_operator:: kube:: Resource ;
@@ -149,7 +165,7 @@ mod tests {
149165 #[ test]
150166 fn build_produces_expected_resources ( ) {
151167 let cluster = minimal_validated_cluster ( ) ;
152- let resources = build ( & cluster, "simple-nifi-serviceaccount" ) . expect ( "build succeeds" ) ;
168+ let resources = build ( & cluster) . expect ( "build succeeds" ) ;
153169
154170 // The minimal fixture has a single `default` role group for the `node` role.
155171 assert_eq ! (
@@ -168,5 +184,14 @@ mod tests {
168184 sorted_names( & resources. pod_disruption_budgets) ,
169185 [ "simple-nifi-node" ]
170186 ) ;
187+ // The cluster-shared RBAC pair.
188+ assert_eq ! (
189+ sorted_names( & resources. service_accounts) ,
190+ [ "simple-nifi-serviceaccount" ]
191+ ) ;
192+ assert_eq ! (
193+ sorted_names( & resources. role_bindings) ,
194+ [ "simple-nifi-rolebinding" ]
195+ ) ;
171196 }
172197}
0 commit comments