-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathhdfs_clusterrolebinding_nodes_controller.rs
More file actions
117 lines (112 loc) · 4.09 KB
/
Copy pathhdfs_clusterrolebinding_nodes_controller.rs
File metadata and controls
117 lines (112 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use serde_json::json;
use stackable_operator::{
commons::rbac::build_rbac_resources,
k8s_openapi::api::rbac::v1::{ClusterRoleBinding, Subject},
kube::{
Api, Client, ResourceExt,
api::{Patch, PatchParams},
core::PartialObjectMeta,
runtime::{
reflector::{ObjectRef, Store},
watcher,
},
},
kvp::Labels,
};
use tracing::{error, info};
use crate::crd::{
constants::{APP_NAME, FIELD_MANAGER_SCOPE},
v1alpha1,
};
pub async fn reconcile(
client: Client,
store: &Store<PartialObjectMeta<v1alpha1::HdfsCluster>>,
ev: watcher::Result<watcher::Event<PartialObjectMeta<v1alpha1::HdfsCluster>>>,
) {
match ev {
Ok(watcher::Event::Apply(o)) => {
info!(object = %ObjectRef::from_obj(&o), "saw updated object")
}
Ok(watcher::Event::Delete(o)) => {
info!(object = %ObjectRef::from_obj(&o), "saw deleted object")
}
Ok(watcher::Event::InitApply(o)) => {
info!(object = %ObjectRef::from_obj(&o), "restarted reflector")
}
Ok(watcher::Event::Init) | Ok(watcher::Event::InitDone) => {}
Err(error) => {
error!(
error = &error as &dyn std::error::Error,
"failed to update reflector"
)
}
}
// Build a list of SubjectRef objects for all deployed HdfsClusters.
// To do this we only need the metadata for that, as we only really
// need name and namespace of the objects
let subjects: Vec<Subject> = store
.state()
.into_iter()
.filter_map(|object| {
// The call to 'build_rbac_resources' can fail, so we
// use filter_map here, log an error for any failures and keep
// going with all the non-broken elements
// Usually we'd rather opt for failing completely here, but in this specific instance
// this could mean that one broken cluster somewhere could impact other working clusters
// within the namespace, so we opted for doing everything we can here, instead of failing
// completely.
match build_rbac_resources(&*object, APP_NAME, Labels::default()) {
Ok((service_account, _role_binding)) => {
Some((object.metadata.clone(), service_account.name_any()))
}
Err(e) => {
error!(
?object,
error = &e as &dyn std::error::Error,
"Failed to build serviceAccount name for hdfs cluster"
);
None
}
}
})
.flat_map(|(meta, sa_name)| {
let mut result = vec![Subject {
kind: "ServiceAccount".to_string(),
name: sa_name,
namespace: meta.namespace.clone(),
..Subject::default()
}];
// If a cluster is called hdfs this would result in the same subject
// being written twicex.
// Since we know this vec only contains two elements we can use dedup for
// simply removing this duplicate.
result.dedup();
result
})
.collect();
let patch = Patch::Apply(json!({
"apiVersion": "rbac.authorization.k8s.io/v1".to_string(),
"kind": "ClusterRoleBinding".to_string(),
"metadata": {
"name": "hdfs-clusterrolebinding-nodes".to_string()
},
"roleRef": {
"apiGroup": "rbac.authorization.k8s.io".to_string(),
"kind": "ClusterRole".to_string(),
"name": "hdfs-clusterrole-nodes".to_string()
},
"subjects": subjects
}));
let api: Api<ClusterRoleBinding> = Api::all(client);
let params = PatchParams::apply(FIELD_MANAGER_SCOPE);
match api
.patch("hdfs-clusterrolebinding-nodes", ¶ms, &patch)
.await
{
Ok(_) => info!(
"ClusterRoleBinding has been successfully patched: {:?}",
&patch
),
Err(e) => error!("{}", e),
}
}