Skip to content

Commit db8e4d2

Browse files
committed
Refactor exit node reconciliation logic
1 parent 14b3530 commit db8e4d2

File tree

1 file changed

+88
-51
lines changed

1 file changed

+88
-51
lines changed

src/daemon.rs

Lines changed: 88 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -579,79 +579,116 @@ async fn reconcile_nodes(obj: Arc<ExitNode>, ctx: Arc<Context>) -> Result<Action
579579
return Ok(Action::await_change());
580580
}
581581

582+
let exit_nodes: Api<ExitNode> = Api::namespaced(ctx.client.clone(), &obj.namespace().unwrap());
583+
582584
let provisioner = obj
583585
.metadata
584586
.annotations
585587
.as_ref()
586588
.and_then(|annotations| annotations.get(EXIT_NODE_PROVISIONER_LABEL))
587-
.unwrap();
588-
589-
let provisioner = find_exit_node_provisioner_from_label(ctx.clone(), provisioner)
590-
.await
591-
.ok_or(ReconcileError::CloudProvisionerNotFound)?;
592-
593-
let exit_nodes: Api<ExitNode> = Api::namespaced(ctx.client.clone(), &obj.namespace().unwrap());
589+
.and_then(|provisioner| {
590+
find_exit_node_provisioner_from_label(ctx.clone(), provisioner)
591+
.now_or_never()
592+
.unwrap()
593+
});
594594

595-
let provisioner_api = provisioner.clone().spec.get_inner();
595+
let provisioner_api = provisioner
596+
.clone()
597+
.map(|provisioner| provisioner.spec.get_inner());
596598

597599
// finalizer for exit node
598600
let secret = provisioner
599-
.find_secret()
600-
.await
601-
.or_else(|_| Err(crate::error::ReconcileError::CloudProvisionerSecretNotFound))?
602-
.ok_or(ReconcileError::CloudProvisionerSecretNotFound)?;
601+
.clone()
602+
.and_then(|provisioner| {
603+
provisioner
604+
.clone()
605+
.find_secret()
606+
.now_or_never()
607+
.or_else(|| {
608+
Some(Err(ReconcileError::KubeError(kube::Error::Api(
609+
kube::error::ErrorResponse {
610+
code: 500,
611+
message: format!(
612+
"Error finding secret for provisioner {}",
613+
provisioner.name_any()
614+
),
615+
reason: "SecretNotFound".to_string(),
616+
status: "Failure".to_string(),
617+
},
618+
))
619+
.into()))
620+
})
621+
})
622+
.unwrap_or_else(|| {
623+
let provisioner = provisioner.clone().unwrap();
624+
Err(color_eyre::eyre::anyhow!(
625+
"Error finding secret for provisioner {}",
626+
provisioner.name_any()
627+
))
628+
})?;
603629

604630
let serverside = PatchParams::apply(OPERATOR_MANAGER).validation_strict();
605-
606-
//? maybe we move this to finalizer's apply function?
607-
608-
let _node = {
609-
let cloud_resource = if let Some(_status) = obj.status.as_ref() {
610-
info!("Updating cloud resource for {}", obj.name_any());
611-
provisioner_api
612-
.update_exit_node(secret.clone(), (*obj).clone())
613-
.await
614-
} else {
615-
info!("Creating cloud resource for {}", obj.name_any());
616-
provisioner_api
617-
.create_exit_node(secret.clone(), (*obj).clone())
618-
.await
619-
};
620-
// TODO: Don't replace the entire status and object, sadly JSON is better here
621-
let exitnode_patch = serde_json::json!({
622-
"status": cloud_resource?
623-
});
624-
625-
exit_nodes
626-
.patch_status(
627-
// We can unwrap safely since Service is guaranteed to have a name
628-
&obj.name_any(),
629-
&serverside.clone(),
630-
&Patch::Merge(exitnode_patch),
631-
)
632-
.await?
633-
};
631+
// what in the name of all that is good is this
632+
// !? why do we have to unwrap()
634633

635634
// handle deletion
636635
finalizer::finalizer(
637-
&exit_nodes,
636+
&exit_nodes.clone(),
638637
EXIT_NODE_FINALIZER,
639638
obj.clone(),
640639
|event| async move {
641640
let m: std::prelude::v1::Result<Action, crate::error::ReconcileError> = match event {
642-
Event::Apply(_) => Ok(Action::requeue(Duration::from_secs(3600))),
641+
Event::Apply(node) => {
642+
if let Some(provisioner_api) = provisioner_api {
643+
if is_managed {
644+
let secret = secret.unwrap();
645+
let _node = {
646+
let cloud_resource = if let Some(_status) = node.status.as_ref() {
647+
info!("Updating cloud resource for {}", node.name_any());
648+
provisioner_api
649+
.update_exit_node(secret.clone(), (*node).clone())
650+
.await
651+
} else {
652+
info!("Creating cloud resource for {}", node.name_any());
653+
provisioner_api
654+
.create_exit_node(secret.clone(), (*node).clone())
655+
.await
656+
};
657+
// TODO: Don't replace the entire status and object, sadly JSON is better here
658+
let exitnode_patch = serde_json::json!({
659+
"status": cloud_resource?
660+
});
661+
662+
exit_nodes
663+
.patch_status(
664+
// We can unwrap safely since Service is guaranteed to have a name
665+
&node.name_any(),
666+
&serverside.clone(),
667+
&Patch::Merge(exitnode_patch),
668+
)
669+
.await?
670+
};
671+
}
672+
}
673+
674+
Ok(Action::requeue(Duration::from_secs(3600)))
675+
}
643676
Event::Cleanup(node) => {
644677
info!("Cleanup finalizer triggered for {}", node.name_any());
645678

646-
if is_managed {
647-
info!("Deleting cloud resource for {}", node.name_any());
648-
provisioner_api
649-
.delete_exit_node(secret, (*node).clone())
650-
.await
651-
.unwrap_or_else(|e| {
652-
error!(?e, "Error deleting exit node {}", node.name_any())
653-
});
679+
if let Some(provisioner_api) = provisioner_api {
680+
if is_managed {
681+
let secret = secret.unwrap();
682+
info!("Deleting cloud resource for {}", node.name_any());
683+
provisioner_api
684+
.delete_exit_node(secret, (*node).clone())
685+
.await
686+
.unwrap_or_else(|e| {
687+
error!(?e, "Error deleting exit node {}", node.name_any())
688+
});
689+
}
654690
}
691+
655692
Ok(Action::requeue(Duration::from_secs(3600)))
656693
}
657694
};

0 commit comments

Comments
 (0)