Skip to content

Commit 04a3046

Browse files
razvannightkr
andauthored
fix: invalid objects don't stop the reconciliation (#551)
* fix: invalid objects don't stop the reconciliation * Update rust/operator-binary/src/main.rs Co-authored-by: Natalie Klestrup Röijezon <[email protected]> * Update rust/operator-binary/src/main.rs Co-authored-by: Natalie Klestrup Röijezon <[email protected]> * Update rust/operator-binary/src/main.rs Co-authored-by: Natalie Klestrup Röijezon <[email protected]> * Update rust/operator-binary/src/main.rs Co-authored-by: Natalie Klestrup Röijezon <[email protected]> --------- Co-authored-by: Natalie Klestrup Röijezon <[email protected]>
1 parent ed7c03b commit 04a3046

File tree

4 files changed

+126
-52
lines changed

4 files changed

+126
-52
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@
1414
- `podOverrides`
1515
- `affinity`
1616

17+
### Fixed
18+
19+
- Invalid `SupersetCluster`, `DruidConnection` or `AuthenticationClass` objects don't stop the operator from reconciling ([#551]).
20+
1721
[#528]: https://github.com/stackabletech/superset-operator/pull/528
1822
[#530]: https://github.com/stackabletech/superset-operator/pull/530
1923
[#549]: https://github.com/stackabletech/superset-operator/pull/549
24+
[#551]: https://github.com/stackabletech/superset-operator/pull/551
2025

2126
## [24.7.0] - 2024-07-24
2227

rust/operator-binary/src/druid_connection_controller.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use stackable_operator::{
1515
},
1616
kube::{
1717
core::DynamicObject,
18+
core::{error_boundary, DeserializeGuard},
1819
runtime::{controller::Action, reflector::ObjectRef},
1920
ResourceExt,
2021
},
@@ -84,6 +85,11 @@ pub enum Error {
8485
SupersetClusterRetrieval {
8586
source: stackable_operator::client::Error,
8687
},
88+
89+
#[snafu(display("DruidConnection object is invalid"))]
90+
InvalidDruidConnection {
91+
source: error_boundary::InvalidObject,
92+
},
8793
}
8894

8995
type Result<T, E = Error> = std::result::Result<T, E>;
@@ -110,20 +116,25 @@ impl ReconcilerError for Error {
110116
Error::ApplyServiceAccount { .. } => None,
111117
Error::ApplyRoleBinding { .. } => None,
112118
Error::SupersetClusterRetrieval { .. } => None,
119+
Error::InvalidDruidConnection { .. } => None,
113120
}
114121
}
115122
}
116123

117124
pub async fn reconcile_druid_connection(
118-
druid_connection: Arc<DruidConnection>,
125+
druid_connection: Arc<DeserializeGuard<DruidConnection>>,
119126
ctx: Arc<Ctx>,
120127
) -> Result<Action> {
121128
tracing::info!("Starting reconciling DruidConnections");
122129

130+
let druid_connection = druid_connection
131+
.0
132+
.as_ref()
133+
.map_err(error_boundary::InvalidObject::clone)
134+
.context(InvalidDruidConnectionSnafu)?;
123135
let client = &ctx.client;
124136

125-
let (rbac_sa, rbac_rolebinding) =
126-
rbac::build_rbac_resources(druid_connection.as_ref(), APP_NAME);
137+
let (rbac_sa, rbac_rolebinding) = rbac::build_rbac_resources(druid_connection, APP_NAME);
127138
client
128139
.apply_patch(DRUID_CONNECTION_CONTROLLER_NAME, &rbac_sa, &rbac_sa)
129140
.await
@@ -146,7 +157,7 @@ pub async fn reconcile_druid_connection(
146157
&druid_connection.druid_name(),
147158
&druid_connection.druid_namespace().context(
148159
DruidConnectionNoNamespaceSnafu {
149-
druid_connection: ObjectRef::from_obj(&*druid_connection),
160+
druid_connection: ObjectRef::from_obj(druid_connection),
150161
},
151162
)?,
152163
)
@@ -159,7 +170,7 @@ pub async fn reconcile_druid_connection(
159170
&druid_connection.superset_name(),
160171
&druid_connection.superset_namespace().context(
161172
DruidConnectionNoNamespaceSnafu {
162-
druid_connection: ObjectRef::from_obj(&*druid_connection),
173+
druid_connection: ObjectRef::from_obj(druid_connection),
163174
},
164175
)?,
165176
)
@@ -183,7 +194,7 @@ pub async fn reconcile_druid_connection(
183194
&druid_connection.druid_name(),
184195
&druid_connection.druid_namespace().context(
185196
DruidConnectionNoNamespaceSnafu {
186-
druid_connection: ObjectRef::from_obj(&*druid_connection),
197+
druid_connection: ObjectRef::from_obj(druid_connection),
187198
},
188199
)?,
189200
client,
@@ -195,7 +206,7 @@ pub async fn reconcile_druid_connection(
195206
.resolve(DOCKER_IMAGE_BASE_NAME, crate::built_info::PKG_VERSION);
196207
let job = build_import_job(
197208
&superset_cluster,
198-
&druid_connection,
209+
druid_connection,
199210
&resolved_product_image,
200211
&sqlalchemy_str,
201212
&rbac_sa.name_any(),
@@ -209,7 +220,7 @@ pub async fn reconcile_druid_connection(
209220
client
210221
.apply_patch_status(
211222
DRUID_CONNECTION_CONTROLLER_NAME,
212-
&*druid_connection,
223+
druid_connection,
213224
&s.importing(),
214225
)
215226
.await
@@ -236,11 +247,7 @@ pub async fn reconcile_druid_connection(
236247

237248
if let Some(ns) = new_status {
238249
client
239-
.apply_patch_status(
240-
DRUID_CONNECTION_CONTROLLER_NAME,
241-
&*druid_connection,
242-
&ns,
243-
)
250+
.apply_patch_status(DRUID_CONNECTION_CONTROLLER_NAME, druid_connection, &ns)
244251
.await
245252
.context(ApplyStatusSnafu)?;
246253
}
@@ -253,7 +260,7 @@ pub async fn reconcile_druid_connection(
253260
client
254261
.apply_patch_status(
255262
DRUID_CONNECTION_CONTROLLER_NAME,
256-
&*druid_connection,
263+
druid_connection,
257264
&DruidConnectionStatus::new(),
258265
)
259266
.await
@@ -360,6 +367,13 @@ async fn build_import_job(
360367
Ok(job)
361368
}
362369

363-
pub fn error_policy(_obj: Arc<DruidConnection>, _error: &Error, _ctx: Arc<Ctx>) -> Action {
364-
Action::requeue(*Duration::from_secs(5))
370+
pub fn error_policy(
371+
_obj: Arc<DeserializeGuard<DruidConnection>>,
372+
error: &Error,
373+
_ctx: Arc<Ctx>,
374+
) -> Action {
375+
match error {
376+
Error::InvalidDruidConnection { .. } => Action::await_change(),
377+
_ => Action::requeue(*Duration::from_secs(5)),
378+
}
365379
}

rust/operator-binary/src/main.rs

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use stackable_operator::{
1111
core::v1::{ConfigMap, Service},
1212
},
1313
kube::{
14+
core::DeserializeGuard,
1415
runtime::{reflector::ObjectRef, watcher, Controller},
1516
ResourceExt,
1617
},
@@ -86,28 +87,28 @@ async fn main() -> anyhow::Result<()> {
8687
.await?;
8788

8889
let superset_controller_builder = Controller::new(
89-
watch_namespace.get_api::<SupersetCluster>(&client),
90+
watch_namespace.get_api::<DeserializeGuard<SupersetCluster>>(&client),
9091
watcher::Config::default(),
9192
);
9293
let superset_store_1 = superset_controller_builder.store();
9394
let superset_controller = superset_controller_builder
9495
.owns(
95-
watch_namespace.get_api::<Service>(&client),
96+
watch_namespace.get_api::<DeserializeGuard<Service>>(&client),
9697
watcher::Config::default(),
9798
)
9899
.owns(
99-
watch_namespace.get_api::<StatefulSet>(&client),
100+
watch_namespace.get_api::<DeserializeGuard<StatefulSet>>(&client),
100101
watcher::Config::default(),
101102
)
102103
.shutdown_on_signal()
103104
.watches(
104-
client.get_api::<AuthenticationClass>(&()),
105+
client.get_api::<DeserializeGuard<AuthenticationClass>>(&()),
105106
watcher::Config::default(),
106107
move |authentication_class| {
107108
superset_store_1
108109
.state()
109110
.into_iter()
110-
.filter(move |superset: &Arc<SupersetCluster>| {
111+
.filter(move |superset| {
111112
references_authentication_class(superset, &authentication_class)
112113
})
113114
.map(|superset| ObjectRef::from_obj(&*superset))
@@ -130,7 +131,7 @@ async fn main() -> anyhow::Result<()> {
130131
});
131132

132133
let druid_connection_controller_builder = Controller::new(
133-
watch_namespace.get_api::<DruidConnection>(&client),
134+
watch_namespace.get_api::<DeserializeGuard<DruidConnection>>(&client),
134135
watcher::Config::default(),
135136
);
136137
let druid_connection_store_1 = druid_connection_controller_builder.store();
@@ -139,46 +140,38 @@ async fn main() -> anyhow::Result<()> {
139140
let druid_connection_controller = druid_connection_controller_builder
140141
.shutdown_on_signal()
141142
.watches(
142-
watch_namespace.get_api::<SupersetCluster>(&client),
143+
watch_namespace.get_api::<DeserializeGuard<SupersetCluster>>(&client),
143144
watcher::Config::default(),
144145
move |superset_cluster| {
145146
druid_connection_store_1
146147
.state()
147148
.into_iter()
148149
.filter(move |druid_connection| {
149-
druid_connection.superset_name() == superset_cluster.name_any()
150-
&& druid_connection.superset_namespace().ok()
151-
== superset_cluster.namespace()
150+
valid_druid_connection(&superset_cluster, druid_connection)
152151
})
153152
.map(|druid_connection| ObjectRef::from_obj(&*druid_connection))
154153
},
155154
)
156155
.watches(
157-
watch_namespace.get_api::<Job>(&client),
156+
watch_namespace.get_api::<DeserializeGuard<Job>>(&client),
158157
watcher::Config::default(),
159158
move |job| {
160159
druid_connection_store_2
161160
.state()
162161
.into_iter()
163-
.filter(move |druid_connection| {
164-
druid_connection.metadata.namespace == job.metadata.namespace
165-
&& Some(druid_connection.job_name()) == job.metadata.name
166-
})
162+
.filter(move |druid_connection| valid_druid_job(druid_connection, &job))
167163
.map(|druid_connection| ObjectRef::from_obj(&*druid_connection))
168164
},
169165
)
170166
.watches(
171-
watch_namespace.get_api::<ConfigMap>(&client),
167+
watch_namespace.get_api::<DeserializeGuard<ConfigMap>>(&client),
172168
watcher::Config::default(),
173169
move |config_map| {
174170
druid_connection_store_3
175171
.state()
176172
.into_iter()
177173
.filter(move |druid_connection| {
178-
druid_connection.druid_namespace().ok()
179-
== config_map.metadata.namespace
180-
&& Some(druid_connection.druid_name())
181-
== config_map.metadata.name
174+
valid_druid_connection_namespace(druid_connection, &config_map)
182175
})
183176
.map(|druid_connection| ObjectRef::from_obj(&*druid_connection))
184177
},
@@ -208,9 +201,13 @@ async fn main() -> anyhow::Result<()> {
208201
}
209202

210203
fn references_authentication_class(
211-
superset: &SupersetCluster,
212-
authentication_class: &AuthenticationClass,
204+
superset: &DeserializeGuard<SupersetCluster>,
205+
authentication_class: &DeserializeGuard<AuthenticationClass>,
213206
) -> bool {
207+
let Ok(superset) = &superset.0 else {
208+
return false;
209+
};
210+
214211
let authentication_class_name = authentication_class.name_any();
215212
superset
216213
.spec
@@ -219,3 +216,36 @@ fn references_authentication_class(
219216
.iter()
220217
.any(|c| c.common.authentication_class_name() == &authentication_class_name)
221218
}
219+
220+
fn valid_druid_connection(
221+
superset_cluster: &DeserializeGuard<SupersetCluster>,
222+
druid_connection: &DeserializeGuard<DruidConnection>,
223+
) -> bool {
224+
let Ok(druid_connection) = &druid_connection.0 else {
225+
return false;
226+
};
227+
druid_connection.superset_name() == superset_cluster.name_any()
228+
&& druid_connection.superset_namespace().ok() == superset_cluster.namespace()
229+
}
230+
231+
fn valid_druid_connection_namespace(
232+
druid_connection: &DeserializeGuard<DruidConnection>,
233+
config_map: &DeserializeGuard<ConfigMap>,
234+
) -> bool {
235+
let Ok(druid_connection) = &druid_connection.0 else {
236+
return false;
237+
};
238+
druid_connection.druid_namespace().ok() == config_map.meta().namespace
239+
&& Some(druid_connection.druid_name()) == config_map.meta().name
240+
}
241+
242+
fn valid_druid_job(
243+
druid_connection: &DeserializeGuard<DruidConnection>,
244+
job: &DeserializeGuard<Job>,
245+
) -> bool {
246+
let Ok(druid_connection) = &druid_connection.0 else {
247+
return false;
248+
};
249+
druid_connection.metadata.namespace == job.meta().namespace
250+
&& Some(druid_connection.job_name()) == job.meta().name
251+
}

0 commit comments

Comments
 (0)