Skip to content

Commit 7ce7b67

Browse files
authored
fix: invalid objects don't stop the reconciliation (#657)
* fix: invalid objects don't stop the reconciliation * review feedback
1 parent a61c09d commit 7ce7b67

File tree

3 files changed

+54
-26
lines changed

3 files changed

+54
-26
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file.
2121
- BREAKING: The fields `connection` and `host` on `S3Connection` as well as `bucketName` on `S3Bucket`are now mandatory ([#646]).
2222
- Don't ignore envOverrides ([#633]).
2323
- Don't print credentials to STDOUT during startup. Ideally we should use [config-utils](https://github.com/stackabletech/config-utils), but that's not easy (see [here](https://github.com/stackabletech/trino-operator/tree/fix/secret-printing)) ([#634]).
24+
- Invalid `TrinoCluster`, `TrinoCatalog` or `AuthenticationClass` objects don't stop the operator from reconciliation ([#657])
2425

2526
### Removed
2627

@@ -32,6 +33,7 @@ All notable changes to this project will be documented in this file.
3233
[#638]: https://github.com/stackabletech/trino-operator/pull/638
3334
[#646]: https://github.com/stackabletech/trino-operator/pull/646
3435
[#655]: https://github.com/stackabletech/trino-operator/pull/655
36+
[#657]: https://github.com/stackabletech/trino-operator/pull/657
3537

3638
## [24.7.0] - 2024-07-24
3739

rust/operator-binary/src/controller.rs

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use stackable_operator::{
4444
DeepMerge,
4545
},
4646
kube::{
47+
core::{error_boundary, DeserializeGuard},
4748
runtime::{controller::Action, reflector::ObjectRef},
4849
Resource, ResourceExt,
4950
},
@@ -331,6 +332,11 @@ pub enum Error {
331332
AddVolumeMount {
332333
source: builder::pod::container::Error,
333334
},
335+
336+
#[snafu(display("invalid TrinoCluster object"))]
337+
InvalidTrinoCluster {
338+
source: error_boundary::InvalidObject,
339+
},
334340
}
335341

336342
type Result<T, E = Error> = std::result::Result<T, E>;
@@ -341,9 +347,17 @@ impl ReconcilerError for Error {
341347
}
342348
}
343349

344-
pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<Action> {
350+
pub async fn reconcile_trino(
351+
trino: Arc<DeserializeGuard<TrinoCluster>>,
352+
ctx: Arc<Ctx>,
353+
) -> Result<Action> {
345354
tracing::info!("Starting reconcile");
346355

356+
let trino = trino
357+
.0
358+
.as_ref()
359+
.map_err(error_boundary::InvalidObject::clone)
360+
.context(InvalidTrinoClusterSnafu)?;
347361
let client = &ctx.client;
348362

349363
let resolved_product_image: ResolvedProductImage = trino
@@ -387,7 +401,7 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
387401
}
388402

389403
let validated_config = validated_product_config(
390-
&trino,
404+
trino,
391405
// The Trino version is a single number like 396.
392406
// The product config expects semver formatted version strings.
393407
// That is why we just add minor and patch version 0 here.
@@ -405,7 +419,7 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
405419
.context(CreateClusterResourcesSnafu)?;
406420

407421
let (rbac_sa, rbac_rolebinding) = build_rbac_resources(
408-
trino.as_ref(),
422+
trino,
409423
APP_NAME,
410424
cluster_resources
411425
.get_required_labels()
@@ -425,23 +439,23 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
425439

426440
let trino_opa_config = match trino.get_opa_config() {
427441
Some(opa_config) => Some(
428-
TrinoOpaConfig::from_opa_config(client, &trino, opa_config)
442+
TrinoOpaConfig::from_opa_config(client, trino, opa_config)
429443
.await
430444
.context(InvalidOpaConfigSnafu)?,
431445
),
432446
None => None,
433447
};
434448

435-
let coordinator_role_service = build_coordinator_role_service(&trino, &resolved_product_image)?;
449+
let coordinator_role_service = build_coordinator_role_service(trino, &resolved_product_image)?;
436450

437451
cluster_resources
438452
.add(client, coordinator_role_service)
439453
.await
440454
.context(ApplyRoleServiceSnafu)?;
441455

442-
create_shared_internal_secret(&trino, client).await?;
456+
create_shared_internal_secret(trino, client).await?;
443457

444-
let vector_aggregator_address = resolve_vector_aggregator_address(&trino, client)
458+
let vector_aggregator_address = resolve_vector_aggregator_address(trino, client)
445459
.await
446460
.context(ResolveVectorAggregatorAddressSnafu)?;
447461

@@ -450,15 +464,15 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
450464
for (role, role_config) in validated_config {
451465
let trino_role = TrinoRole::from_str(&role).context(FailedToParseRoleSnafu)?;
452466
for (role_group, config) in role_config {
453-
let rolegroup = trino_role.rolegroup_ref(&trino, role_group);
467+
let rolegroup = trino_role.rolegroup_ref(trino, role_group);
454468

455469
let merged_config = trino
456470
.merged_config(&trino_role, &rolegroup, &catalog_definitions)
457471
.context(FailedToResolveConfigSnafu)?;
458472

459-
let rg_service = build_rolegroup_service(&trino, &resolved_product_image, &rolegroup)?;
473+
let rg_service = build_rolegroup_service(trino, &resolved_product_image, &rolegroup)?;
460474
let rg_configmap = build_rolegroup_config_map(
461-
&trino,
475+
trino,
462476
&resolved_product_image,
463477
&trino_role,
464478
&rolegroup,
@@ -470,13 +484,13 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
470484
&client.kubernetes_cluster_info,
471485
)?;
472486
let rg_catalog_configmap = build_rolegroup_catalog_config_map(
473-
&trino,
487+
trino,
474488
&resolved_product_image,
475489
&rolegroup,
476490
&catalogs,
477491
)?;
478492
let rg_stateful_set = build_rolegroup_statefulset(
479-
&trino,
493+
trino,
480494
&trino_role,
481495
&resolved_product_image,
482496
&rolegroup,
@@ -523,7 +537,7 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
523537
pod_disruption_budget: pdb,
524538
}) = role_config
525539
{
526-
add_pdbs(pdb, &trino, &trino_role, client, &mut cluster_resources)
540+
add_pdbs(pdb, trino, &trino_role, client, &mut cluster_resources)
527541
.await
528542
.context(FailedToCreatePdbSnafu)?;
529543
}
@@ -534,7 +548,7 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
534548

535549
let status = TrinoClusterStatus {
536550
conditions: compute_conditions(
537-
trino.as_ref(),
551+
trino,
538552
&[&sts_cond_builder, &cluster_operation_cond_builder],
539553
),
540554
};
@@ -544,7 +558,7 @@ pub async fn reconcile_trino(trino: Arc<TrinoCluster>, ctx: Arc<Ctx>) -> Result<
544558
.await
545559
.context(DeleteOrphanedResourcesSnafu)?;
546560
client
547-
.apply_patch_status(OPERATOR_NAME, &*trino, &status)
561+
.apply_patch_status(OPERATOR_NAME, trino, &status)
548562
.await
549563
.context(ApplyStatusSnafu)?;
550564

@@ -1221,8 +1235,15 @@ fn build_rolegroup_service(
12211235
})
12221236
}
12231237

1224-
pub fn error_policy(_obj: Arc<TrinoCluster>, _error: &Error, _ctx: Arc<Ctx>) -> Action {
1225-
Action::requeue(*Duration::from_secs(5))
1238+
pub fn error_policy(
1239+
_obj: Arc<DeserializeGuard<TrinoCluster>>,
1240+
error: &Error,
1241+
_ctx: Arc<Ctx>,
1242+
) -> Action {
1243+
match error {
1244+
Error::InvalidTrinoCluster { .. } => Action::await_change(),
1245+
_ => Action::requeue(*Duration::from_secs(5)),
1246+
}
12261247
}
12271248

12281249
/// Give a secret name and an optional key in the secret to use.

rust/operator-binary/src/main.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use stackable_operator::{
1919
core::v1::{ConfigMap, Service},
2020
},
2121
kube::{
22+
core::DeserializeGuard,
2223
runtime::{reflector::ObjectRef, watcher, Controller},
2324
ResourceExt,
2425
},
@@ -78,28 +79,28 @@ async fn main() -> anyhow::Result<()> {
7879
.await?;
7980

8081
let cluster_controller = Controller::new(
81-
watch_namespace.get_api::<TrinoCluster>(&client),
82+
watch_namespace.get_api::<DeserializeGuard<TrinoCluster>>(&client),
8283
watcher::Config::default(),
8384
);
8485
let catalog_cluster_store = Arc::new(cluster_controller.store());
8586
let authentication_class_cluster_store = catalog_cluster_store.clone();
8687

8788
cluster_controller
8889
.owns(
89-
watch_namespace.get_api::<Service>(&client),
90+
watch_namespace.get_api::<DeserializeGuard<Service>>(&client),
9091
watcher::Config::default(),
9192
)
9293
.owns(
93-
watch_namespace.get_api::<StatefulSet>(&client),
94+
watch_namespace.get_api::<DeserializeGuard<StatefulSet>>(&client),
9495
watcher::Config::default(),
9596
)
9697
.owns(
97-
watch_namespace.get_api::<ConfigMap>(&client),
98+
watch_namespace.get_api::<DeserializeGuard<ConfigMap>>(&client),
9899
watcher::Config::default(),
99100
)
100101
.shutdown_on_signal()
101102
.watches(
102-
watch_namespace.get_api::<TrinoCatalog>(&client),
103+
watch_namespace.get_api::<DeserializeGuard<TrinoCatalog>>(&client),
103104
watcher::Config::default(),
104105
move |catalog| {
105106
// TODO: Filter clusters more precisely based on the catalogLabelSelector to avoid unnecessary reconciles
@@ -112,13 +113,13 @@ async fn main() -> anyhow::Result<()> {
112113
},
113114
)
114115
.watches(
115-
client.get_api::<AuthenticationClass>(&()),
116+
client.get_api::<DeserializeGuard<AuthenticationClass>>(&()),
116117
watcher::Config::default(),
117118
move |authentication_class| {
118119
authentication_class_cluster_store
119120
.state()
120121
.into_iter()
121-
.filter(move |trino: &Arc<TrinoCluster>| {
122+
.filter(move |trino| {
122123
references_authentication_class(trino, &authentication_class)
123124
})
124125
.map(|trino| ObjectRef::from_obj(&*trino))
@@ -148,9 +149,13 @@ async fn main() -> anyhow::Result<()> {
148149
}
149150

150151
fn references_authentication_class(
151-
trino: &TrinoCluster,
152-
authentication_class: &AuthenticationClass,
152+
trino: &DeserializeGuard<TrinoCluster>,
153+
authentication_class: &DeserializeGuard<AuthenticationClass>,
153154
) -> bool {
155+
let Ok(trino) = &trino.0 else {
156+
return false;
157+
};
158+
154159
let authentication_class_name = authentication_class.name_any();
155160
trino
156161
.spec

0 commit comments

Comments
 (0)