modelexpress_server/registry/
k8s_types.rs1use kube::CustomResource;
12use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14
15#[derive(CustomResource, Clone, Debug, Deserialize, Serialize, JsonSchema)]
17#[kube(
18 group = "modelexpress.nvidia.com",
19 version = "v1alpha1",
20 kind = "ModelCacheEntry",
21 plural = "modelcacheentries",
22 shortname = "mxcache",
23 namespaced,
24 status = "ModelCacheEntryStatus"
25)]
26pub struct ModelCacheEntrySpec {
27 #[serde(rename = "modelName")]
31 pub model_name: String,
32
33 pub provider: String,
35}
36
37#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema)]
39pub struct ModelCacheEntryStatus {
40 #[serde(default)]
43 pub phase: String,
44
45 #[serde(rename = "createdAt", default)]
47 pub created_at: Option<String>,
48
49 #[serde(rename = "lastUsedAt", default)]
51 pub last_used_at: Option<String>,
52
53 #[serde(default)]
55 pub message: Option<String>,
56}
57
58pub mod phase {
60 pub const DOWNLOADING: &str = "Downloading";
61 pub const DOWNLOADED: &str = "Downloaded";
62 pub const ERROR: &str = "Error";
63}
64
65#[cfg(test)]
66#[allow(clippy::expect_used)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn spec_roundtrips_through_json() {
72 let spec = ModelCacheEntrySpec {
73 model_name: "meta-llama/Llama-3.1-70B".to_string(),
74 provider: "HuggingFace".to_string(),
75 };
76 let json = serde_json::to_string(&spec).expect("serialize");
77 assert!(json.contains("\"modelName\":\"meta-llama/Llama-3.1-70B\""));
78 let back: ModelCacheEntrySpec = serde_json::from_str(&json).expect("deserialize");
79 assert_eq!(back.model_name, spec.model_name);
80 assert_eq!(back.provider, spec.provider);
81 }
82
83 #[test]
84 fn status_default_is_empty() {
85 let status = ModelCacheEntryStatus::default();
86 assert_eq!(status.phase, "");
87 assert!(status.created_at.is_none());
88 assert!(status.last_used_at.is_none());
89 assert!(status.message.is_none());
90 }
91}