cdl_openapi/model_storage/
mod.rs1pub 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}