cdl_openapi/model_storage/
mod.rs

1pub mod object;
2
3use std::collections::BTreeMap;
4
5use byte_unit::Byte;
6use cdl_k8s_core::openapi::Url;
7use chrono::{DateTime, Utc};
8use k8s_openapi::{
9    api::core::v1::ResourceRequirements, apimachinery::pkg::api::resource::Quantity,
10};
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13use strum::{Display, EnumString};
14
15#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
16#[cfg_attr(feature = "k8s", derive(::kube::CustomResource))]
17#[cfg_attr(
18    feature = "k8s",
19    kube(
20        group = "cdl.ulagbulag.io",
21        version = "v1alpha1",
22        kind = "ModelStorage",
23        root = "ModelStorageCrd",
24        status = "ModelStorageStatus",
25        shortname = "ms",
26        namespaced,
27        printcolumn = r#"{
28            "name": "state",
29            "type": "string",
30            "description": "state of the model storage",
31            "jsonPath": ".status.state"
32        }"#,
33        printcolumn = r#"{
34            "name": "created-at",
35            "type": "date",
36            "description": "created time",
37            "jsonPath": ".metadata.creationTimestamp"
38        }"#,
39        printcolumn = r#"{
40            "name": "updated-at",
41            "type": "date",
42            "description": "updated time",
43            "jsonPath": ".status.lastUpdated"
44        }"#,
45    )
46)]
47#[serde(rename_all = "camelCase")]
48pub struct ModelStorageSpec {
49    #[serde(flatten)]
50    pub kind: ModelStorageKindSpec,
51    #[serde(default)]
52    pub default: bool,
53}
54
55#[cfg(feature = "k8s")]
56impl ModelStorageCrd {
57    pub const FINALIZER_NAME: &'static str = "cdl.ulagbulag.io/finalizer-model-storages";
58
59    pub const LABEL_IS_EXTERNAL: &'static str = "ark.ulagbulag.io/is-external";
60}
61
62#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
63#[serde(rename_all = "camelCase")]
64pub enum ModelStorageKindSpec {
65    ObjectStorage(#[serde(default)] self::object::ModelStorageObjectSpec),
66}
67
68impl ModelStorageKindSpec {
69    #[inline]
70    pub fn endpoint(&self, namespace: &str) -> Option<Url> {
71        match self {
72            Self::ObjectStorage(spec) => spec.endpoint(namespace),
73        }
74    }
75
76    pub const fn is_unique(&self) -> bool {
77        match self {
78            Self::ObjectStorage(spec) => spec.is_unique(),
79        }
80    }
81
82    pub const fn to_kind(&self) -> ModelStorageKind {
83        match self {
84            Self::ObjectStorage(_) => ModelStorageKind::ObjectStorage,
85        }
86    }
87}
88
89#[derive(
90    Copy,
91    Clone,
92    Debug,
93    Display,
94    EnumString,
95    PartialEq,
96    Eq,
97    PartialOrd,
98    Ord,
99    Hash,
100    Serialize,
101    Deserialize,
102    JsonSchema,
103)]
104pub enum ModelStorageKind {
105    ObjectStorage,
106}
107
108#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
109#[serde(rename_all = "camelCase")]
110pub struct ModelStorageStatus {
111    #[serde(default)]
112    pub state: ModelStorageState,
113    pub kind: Option<ModelStorageKindSpec>,
114    pub last_updated: DateTime<Utc>,
115    #[serde(default)]
116    pub total_quota: Option<u128>,
117}
118
119#[derive(
120    Copy,
121    Clone,
122    Debug,
123    Display,
124    Default,
125    EnumString,
126    PartialEq,
127    Eq,
128    PartialOrd,
129    Ord,
130    Hash,
131    Serialize,
132    Deserialize,
133    JsonSchema,
134)]
135pub enum ModelStorageState {
136    #[default]
137    Pending,
138    Ready,
139    Deleting,
140}
141
142pub trait StorageResourceRequirements {
143    fn quota(&self) -> Option<Byte>;
144}
145
146impl<T> StorageResourceRequirements for Option<T>
147where
148    T: StorageResourceRequirements,
149{
150    fn quota(&self) -> Option<Byte> {
151        self.as_ref().and_then(|this| this.quota())
152    }
153}
154
155impl StorageResourceRequirements for ResourceRequirements {
156    fn quota(&self) -> Option<Byte> {
157        self.requests.quota()
158    }
159}
160
161impl StorageResourceRequirements for BTreeMap<String, Quantity> {
162    fn quota(&self) -> Option<Byte> {
163        self.get("storage").and_then(|quota| quota.0.parse().ok())
164    }
165}