Skip to content

Commit 882eb00

Browse files
committed
refactor: consolidate rbac resources
1 parent 74dbc46 commit 882eb00

3 files changed

Lines changed: 89 additions & 18 deletions

File tree

rust/operator-binary/src/controller.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ use snafu::{ResultExt, Snafu};
1717
use stackable_operator::{
1818
cli::OperatorEnvironmentOptions,
1919
cluster_resources::ClusterResourceApplyStrategy,
20-
commons::{
21-
networking::DomainName, product_image_selection::ResolvedProductImage,
22-
rbac::build_rbac_resources,
23-
},
20+
commons::{networking::DomainName, product_image_selection::ResolvedProductImage},
2421
crd::listener,
2522
kube::{
2623
Resource,
@@ -65,6 +62,7 @@ use crate::{
6562
resource::{
6663
listener::build_broker_rolegroup_bootstrap_listener,
6764
pdb::build_pdb,
65+
rbac::{build_rbac_role_binding, build_rbac_service_account},
6866
service::{build_rolegroup_headless_service, build_rolegroup_metrics_service},
6967
statefulset::{
7068
build_broker_rolegroup_statefulset, build_controller_rolegroup_statefulset,
@@ -489,11 +487,6 @@ pub enum Error {
489487
source: stackable_operator::client::Error,
490488
},
491489

492-
#[snafu(display("failed to build RBAC resources"))]
493-
BuildRbacResources {
494-
source: stackable_operator::commons::rbac::Error,
495-
},
496-
497490
#[snafu(display("failed to apply PodDisruptionBudget"))]
498491
ApplyPdb {
499492
source: stackable_operator::cluster_resources::Error,
@@ -541,7 +534,6 @@ impl ReconcilerError for Error {
541534
Error::ApplyServiceAccount { .. } => None,
542535
Error::ApplyRoleBinding { .. } => None,
543536
Error::ApplyStatus { .. } => None,
544-
Error::BuildRbacResources { .. } => None,
545537
Error::ApplyPdb { .. } => None,
546538
Error::GetRequiredLabels { .. } => None,
547539
Error::InvalidKafkaCluster { .. } => None,
@@ -596,14 +588,11 @@ pub async fn reconcile_kafka(
596588

597589
let mut ss_cond_builder = StatefulSetConditionBuilder::default();
598590

599-
let (rbac_sa, rbac_rolebinding) = build_rbac_resources(
600-
kafka,
601-
APP_NAME,
602-
cluster_resources
603-
.get_required_labels()
604-
.context(GetRequiredLabelsSnafu)?,
605-
)
606-
.context(BuildRbacResourcesSnafu)?;
591+
let required_labels = cluster_resources
592+
.get_required_labels()
593+
.context(GetRequiredLabelsSnafu)?;
594+
let rbac_sa = build_rbac_service_account(&validated_cluster, required_labels.clone());
595+
let rbac_rolebinding = build_rbac_role_binding(&validated_cluster, required_labels);
607596

608597
let rbac_sa = cluster_resources
609598
.add(client, rbac_sa.clone())

rust/operator-binary/src/controller/build/resource/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ pub mod config_map;
44
pub mod discovery;
55
pub mod listener;
66
pub mod pdb;
7+
pub mod rbac;
78
pub mod service;
89
pub mod statefulset;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//! Builds the cluster-wide RBAC resources (`ServiceAccount` and `RoleBinding`).
2+
//!
3+
//! The names come from the v2 [`ResourceNames`](stackable_operator::v2::role_utils::ResourceNames)
4+
//! and are identical to the previously used `commons::rbac::build_rbac_resources`
5+
//! (`<cluster>-serviceaccount`, `<cluster>-rolebinding`, `<product>-clusterrole`), so switching to
6+
//! this builder does not rename any RBAC objects.
7+
8+
use stackable_operator::{
9+
builder::meta::ObjectMetaBuilder,
10+
k8s_openapi::api::{
11+
core::v1::ServiceAccount,
12+
rbac::v1::{RoleBinding, RoleRef, Subject},
13+
},
14+
kvp::Labels,
15+
v2::{builder::meta::ownerreference_from_resource, role_utils::ResourceNames},
16+
};
17+
18+
use crate::controller::{ValidatedCluster, product_name};
19+
20+
/// Type-safe RBAC resource names for this cluster.
21+
fn rbac_resource_names(validated_cluster: &ValidatedCluster) -> ResourceNames {
22+
ResourceNames {
23+
cluster_name: validated_cluster.name.clone(),
24+
product_name: product_name(),
25+
}
26+
}
27+
28+
/// Builds the [`ServiceAccount`] shared by all role groups, named `<cluster>-serviceaccount`.
29+
pub fn build_rbac_service_account(
30+
validated_cluster: &ValidatedCluster,
31+
labels: Labels,
32+
) -> ServiceAccount {
33+
let resource_names = rbac_resource_names(validated_cluster);
34+
35+
ServiceAccount {
36+
metadata: ObjectMetaBuilder::new()
37+
.name_and_namespace(validated_cluster)
38+
.name(resource_names.service_account_name().to_string())
39+
.ownerreference(ownerreference_from_resource(
40+
validated_cluster,
41+
None,
42+
Some(true),
43+
))
44+
.with_labels(labels)
45+
.build(),
46+
..ServiceAccount::default()
47+
}
48+
}
49+
50+
/// Builds the [`RoleBinding`] (named `<cluster>-rolebinding`) that binds the
51+
/// [`ServiceAccount`] to the `<product>-clusterrole` `ClusterRole`.
52+
pub fn build_rbac_role_binding(
53+
validated_cluster: &ValidatedCluster,
54+
labels: Labels,
55+
) -> RoleBinding {
56+
let resource_names = rbac_resource_names(validated_cluster);
57+
58+
RoleBinding {
59+
metadata: ObjectMetaBuilder::new()
60+
.name_and_namespace(validated_cluster)
61+
.name(resource_names.role_binding_name().to_string())
62+
.ownerreference(ownerreference_from_resource(
63+
validated_cluster,
64+
None,
65+
Some(true),
66+
))
67+
.with_labels(labels)
68+
.build(),
69+
role_ref: RoleRef {
70+
api_group: "rbac.authorization.k8s.io".to_string(),
71+
kind: "ClusterRole".to_string(),
72+
name: resource_names.cluster_role_name().to_string(),
73+
},
74+
subjects: Some(vec![Subject {
75+
kind: "ServiceAccount".to_string(),
76+
name: resource_names.service_account_name().to_string(),
77+
namespace: Some(validated_cluster.namespace.to_string()),
78+
..Subject::default()
79+
}]),
80+
}
81+
}

0 commit comments

Comments
 (0)