use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ResourceKey {
pub group: String,
pub version: String,
pub kind: String,
pub namespace: Option<String>,
pub name: String,
}
impl ResourceKey {
#[must_use]
pub fn namespaced(
group: impl Into<String>,
version: impl Into<String>,
kind: impl Into<String>,
namespace: impl Into<String>,
name: impl Into<String>,
) -> Self {
Self {
group: group.into(),
version: version.into(),
kind: kind.into(),
namespace: Some(namespace.into()),
name: name.into(),
}
}
#[must_use]
pub fn cluster_scoped(
group: impl Into<String>,
version: impl Into<String>,
kind: impl Into<String>,
name: impl Into<String>,
) -> Self {
Self {
group: group.into(),
version: version.into(),
kind: kind.into(),
namespace: None,
name: name.into(),
}
}
#[must_use]
pub fn label(&self) -> String {
let group = if self.group.is_empty() {
"v1"
} else {
self.group.as_str()
};
match &self.namespace {
Some(ns) => format!("{group}/{}/{}/{ns}/{}", self.version, self.kind, self.name),
None => format!("{group}/{}/{}/{}", self.version, self.kind, self.name),
}
}
}
pub type ResourceValue = serde_json::Value;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resource_key_label_is_stable() {
let k = ResourceKey::namespaced("", "v1", "Pod", "default", "podinfo");
assert_eq!(k.label(), "v1/v1/Pod/default/podinfo");
let c = ResourceKey::cluster_scoped("", "v1", "Namespace", "default");
assert_eq!(c.label(), "v1/v1/Namespace/default");
let r = ResourceKey::namespaced(
"apps",
"v1",
"Deployment",
"default",
"podinfo",
);
assert_eq!(r.label(), "apps/v1/Deployment/default/podinfo");
}
#[test]
fn resource_key_serde_round_trips() {
let k = ResourceKey::namespaced("apps", "v1", "Deployment", "kube-system", "coredns");
let json = serde_json::to_string(&k).unwrap();
let back: ResourceKey = serde_json::from_str(&json).unwrap();
assert_eq!(back, k);
}
#[test]
fn resource_keys_are_ordered() {
let a = ResourceKey::namespaced("", "v1", "Pod", "default", "a");
let b = ResourceKey::namespaced("", "v1", "Pod", "default", "b");
let c = ResourceKey::namespaced("apps", "v1", "Deployment", "default", "a");
let mut v = vec![b.clone(), c.clone(), a.clone()];
v.sort();
assert_eq!(v, vec![a, b, c]);
}
}