cdl_openapi/model_storage/
object.rs

1use std::net::Ipv4Addr;
2
3use cdl_k8s_core::openapi::Url;
4use k8s_openapi::{
5    api::core::v1::ResourceRequirements, apimachinery::pkg::api::resource::Quantity,
6};
7use maplit::btreemap;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10
11use crate::model_user::ModelUserAccessTokenSecretRefSpec;
12
13#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
14#[serde(rename_all = "camelCase")]
15pub enum ModelStorageObjectSpec {
16    Borrowed(ModelStorageObjectBorrowedSpec),
17    Cloned(ModelStorageObjectClonedSpec),
18    Owned(#[serde(default)] ModelStorageObjectOwnedSpec),
19}
20
21impl Default for ModelStorageObjectSpec {
22    fn default() -> Self {
23        Self::Owned(Default::default())
24    }
25}
26
27impl ModelStorageObjectSpec {
28    #[inline]
29    pub(super) fn endpoint(&self, namespace: &str) -> Option<Url> {
30        match self {
31            Self::Borrowed(spec) => spec.endpoint(),
32            Self::Cloned(spec) => spec.endpoint(namespace),
33            Self::Owned(spec) => spec.endpoint(namespace),
34        }
35    }
36
37    pub(super) const fn is_unique(&self) -> bool {
38        match self {
39            Self::Borrowed(_) => false,
40            Self::Cloned(_) => true,
41            Self::Owned(_) => true,
42        }
43    }
44}
45
46#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
47#[serde(rename_all = "camelCase")]
48pub struct ModelStorageObjectBorrowedSpec {
49    #[serde(default, flatten)]
50    pub reference: ModelStorageObjectRefSpec,
51}
52
53impl ModelStorageObjectBorrowedSpec {
54    #[inline]
55    fn endpoint(&self) -> Option<Url> {
56        self.reference.endpoint()
57    }
58}
59
60#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
61#[serde(rename_all = "camelCase")]
62pub struct ModelStorageObjectClonedSpec {
63    #[serde(flatten)]
64    pub reference: ModelStorageObjectRefSpec,
65
66    #[serde(default, flatten)]
67    pub owned: ModelStorageObjectOwnedSpec,
68}
69
70impl ModelStorageObjectClonedSpec {
71    #[inline]
72    fn endpoint(&self, namespace: &str) -> Option<Url> {
73        self.owned.endpoint(namespace)
74    }
75}
76
77#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
78#[serde(rename_all = "camelCase")]
79pub struct ModelStorageObjectOwnedSpec {
80    #[serde(default)]
81    pub minio_console_external_service: ModelStorageObjectOwnedExternalServiceSpec,
82
83    #[serde(default)]
84    pub minio_external_service: ModelStorageObjectOwnedExternalServiceSpec,
85
86    #[serde(default, flatten)]
87    pub replication: ModelStorageObjectOwnedReplicationSpec,
88
89    #[serde(default = "ModelStorageObjectOwnedSpec::default_runtime_class_name")]
90    pub runtime_class_name: String,
91
92    #[serde(default = "ModelStorageObjectOwnedSpec::default_storage_class_name")]
93    pub storage_class_name: String,
94}
95
96impl Default for ModelStorageObjectOwnedSpec {
97    fn default() -> Self {
98        Self {
99            minio_console_external_service: Default::default(),
100            minio_external_service: Default::default(),
101            replication: Default::default(),
102            runtime_class_name: Self::default_runtime_class_name(),
103            storage_class_name: Self::default_storage_class_name(),
104        }
105    }
106}
107
108impl ModelStorageObjectOwnedSpec {
109    fn default_runtime_class_name() -> String {
110        Default::default()
111    }
112
113    fn default_storage_class_name() -> String {
114        "ceph-block".into()
115    }
116
117    #[inline]
118    fn endpoint(&self, namespace: &str) -> Option<Url> {
119        get_object_storage_endpoint(namespace)
120    }
121}
122
123#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
124#[serde(rename_all = "camelCase")]
125pub struct ModelStorageObjectOwnedReplicationSpec {
126    #[serde(default = "ModelStorageObjectOwnedReplicationSpec::default_resources")]
127    pub resources: ResourceRequirements,
128
129    #[serde(default = "ModelStorageObjectOwnedReplicationSpec::default_total_nodes")]
130    pub total_nodes: u32,
131
132    #[serde(default = "ModelStorageObjectOwnedReplicationSpec::default_total_volumes_per_node")]
133    pub total_volumes_per_node: u32,
134}
135
136impl Default for ModelStorageObjectOwnedReplicationSpec {
137    fn default() -> Self {
138        Self {
139            resources: Self::default_resources(),
140            total_nodes: Self::default_total_nodes(),
141            total_volumes_per_node: Self::default_total_volumes_per_node(),
142        }
143    }
144}
145
146impl ModelStorageObjectOwnedReplicationSpec {
147    pub const fn default_resources_cpu() -> &'static str {
148        "8"
149    }
150
151    pub const fn default_resources_memory() -> &'static str {
152        "16Gi"
153    }
154
155    pub const fn default_resources_storage() -> &'static str {
156        "1TiB"
157    }
158
159    fn default_resources() -> ResourceRequirements {
160        ResourceRequirements {
161            limits: Some(btreemap! {
162                "cpu".into() => Quantity(Self::default_resources_cpu().into()),
163                "memory".into() => Quantity(Self::default_resources_memory().into()),
164            }),
165            requests: Some(btreemap! {
166                "storage".into() => Quantity(Self::default_resources_storage().into()),
167            }),
168            ..Default::default()
169        }
170    }
171
172    const fn default_total_nodes() -> u32 {
173        4
174    }
175
176    const fn default_total_volumes_per_node() -> u32 {
177        4
178    }
179}
180
181#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
182#[serde(rename_all = "camelCase")]
183pub struct ModelStorageObjectOwnedExternalServiceSpec {
184    #[serde(default)]
185    pub address_pool: Option<String>,
186
187    #[serde(default)]
188    pub ip: Option<Ipv4Addr>,
189}
190
191impl ModelStorageObjectOwnedExternalServiceSpec {
192    pub const fn is_enabled(&self) -> bool {
193        self.address_pool.is_some() || self.ip.is_some()
194    }
195}
196
197#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
198#[serde(rename_all = "camelCase")]
199pub struct ModelStorageObjectRefSpec {
200    pub endpoint: Url,
201    #[serde(default)]
202    pub secret_ref: ModelUserAccessTokenSecretRefSpec,
203}
204
205impl ModelStorageObjectRefSpec {
206    #[inline]
207    fn endpoint(&self) -> Option<Url> {
208        Some(self.endpoint.clone())
209    }
210}
211
212#[inline]
213pub fn get_object_storage_endpoint(namespace: &str) -> Option<Url> {
214    format!("http://object-storage.{namespace}.svc")
215        .parse()
216        .ok()
217}
218
219#[inline]
220pub fn get_object_storage_owned_endpoint(namespace: &str) -> Option<Url> {
221    format!("http://minio.{namespace}.svc").parse().ok()
222}