use std::fmt::Debug;
use kube::api::{Patch, PatchParams};
use kube::{Api, Client};
use serde::de::DeserializeOwned;
use serde_json::json;
use tracing::info;
use crate::error::Result;
use crate::scope::{ApiScope, Namespaced};
use crate::traits::{KubeResource, NamespacedResource};
async fn apply_finalizer_patch<T>(api: Api<T>, name: &str, patch: serde_json::Value) -> Result<T>
where
T: Clone + Debug + DeserializeOwned,
{
Ok(api
.patch(name, &PatchParams::default(), &Patch::Merge(&patch))
.await?)
}
pub async fn add_finalizer<T, Scope>(
client: Client,
scope: Scope,
resource: &T,
finalizer: &str,
) -> Result<T>
where
T: KubeResource,
Scope: ApiScope<T>,
{
let name = resource
.meta()
.name
.as_deref()
.ok_or_else(|| crate::error::KubeGenericError::MissingMetadata("name".into()))?;
if resource
.meta()
.finalizers
.as_deref()
.unwrap_or(&[])
.iter()
.any(|f| f == finalizer)
{
return Ok(resource.clone());
}
let kind = T::kind(&());
match scope.namespace() {
Some(namespace) => info!(%namespace, %kind, %name, %finalizer, "Adding finalizer"),
None => info!(%kind, %name, %finalizer, "Adding finalizer"),
}
let mut finalizers: Vec<String> = resource.meta().finalizers.clone().unwrap_or_default();
finalizers.push(finalizer.to_string());
let patch = json!({ "metadata": { "finalizers": finalizers } });
apply_finalizer_patch(scope.into_api(client), name, patch).await
}
pub async fn remove_finalizers<T, Scope>(client: Client, scope: Scope, name: &str) -> Result<T>
where
T: KubeResource,
Scope: ApiScope<T>,
{
let kind = T::kind(&());
match scope.namespace() {
Some(namespace) => info!(%namespace, %kind, %name, "Removing all finalizers"),
None => info!(%kind, %name, "Removing all finalizers"),
}
let patch = json!({ "metadata": { "finalizers": null } });
apply_finalizer_patch(scope.into_api(client), name, patch).await
}
pub async fn add_finalizer_namespaced<T>(client: Client, resource: &T, finalizer: &str) -> Result<T>
where
T: NamespacedResource,
{
let namespace = resource
.meta()
.namespace
.as_deref()
.ok_or_else(|| crate::error::KubeGenericError::MissingMetadata("namespace".into()))?;
add_finalizer::<T, _>(client, Namespaced(namespace), resource, finalizer).await
}