use std::collections::HashMap;
use std::sync::Arc;
#[cfg(not(feature = "admission-webhook"))]
use kube::api::DynamicObject;
use kube::api::GroupVersionKind;
use serde::de::DeserializeOwned;
use tokio::sync::RwLock;
use crate::object::ObjectKey;
type ResourceMap = HashMap<GroupVersionKind, HashMap<ObjectKey, serde_json::Value>>;
#[derive(Clone)]
pub struct Store {
objects: Arc<RwLock<ResourceMap>>,
}
impl Default for Store {
fn default() -> Self {
Store::new()
}
}
impl Store {
pub fn new() -> Self {
Store {
objects: Arc::new(RwLock::new(HashMap::new())),
}
}
#[cfg(not(feature = "admission-webhook"))]
pub(crate) async fn reset(&self, gvk: &GroupVersionKind) {
let mut objects = self.objects.write().await;
let key = gvk.clone();
let resource_objects = (*objects).entry(key).or_insert_with(HashMap::new);
resource_objects.clear();
}
#[cfg(not(feature = "admission-webhook"))]
pub(crate) async fn delete_gvk(
&self,
namespace: Option<String>,
name: String,
gvk: &GroupVersionKind,
) {
let mut objects = self.objects.write().await;
let key = gvk.clone();
let resource_objects = (*objects).entry(key).or_insert_with(HashMap::new);
let object_key = ObjectKey::new(namespace, name);
resource_objects.remove(&object_key);
}
#[cfg(not(feature = "admission-webhook"))]
pub(crate) async fn insert_gvk(
&self,
namespace: Option<String>,
name: String,
gvk: &GroupVersionKind,
dynamic_object: DynamicObject,
) {
let mut objects = self.objects.write().await;
let key = gvk.clone();
let resource_objects = (*objects).entry(key).or_insert_with(HashMap::new);
let object_key = ObjectKey::new(namespace, name);
resource_objects.insert(object_key, serde_json::to_value(&dynamic_object).unwrap());
}
pub async fn get<R: 'static + k8s_openapi::Resource + Clone + DeserializeOwned>(
&self,
namespace: Option<&str>,
name: &str,
) -> anyhow::Result<Option<R>> {
let objects = self.objects.read().await;
let key = GroupVersionKind::gvk(R::GROUP, R::VERSION, R::KIND);
let object_key = ObjectKey::new(namespace.map(|s| s.to_string()), name.to_string());
match (*objects).get(&key) {
Some(resource_objects) => match resource_objects.get(&object_key) {
Some(value) => match serde_json::from_value::<R>(value.clone()) {
Ok(object) => Ok(Some(object)),
Err(e) => {
anyhow::bail!(
"Could not interpret interred object as type {}/{} {}: {:?}",
R::GROUP,
R::VERSION,
R::KIND,
e
);
}
},
None => Ok(None),
},
None => Ok(None),
}
}
}