k8_obj_app/
stateful.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4use k8_obj_core::pod::PodSpec;
5use crate::core::metadata::{Crd, CrdNames, DefaultHeader, LabelSelector, Spec, Status, TemplateSpec};
6
7const STATEFUL_API: Crd = Crd {
8    group: "apps",
9    version: "v1",
10    names: CrdNames {
11        kind: "StatefulSet",
12        plural: "statefulsets",
13        singular: "statefulset",
14    },
15};
16
17#[derive(Deserialize, Serialize, Debug, Default, Clone)]
18#[serde(rename_all = "camelCase", default)]
19pub struct StatefulSetSpec {
20    pub pod_management_policy: Option<PodMangementPolicy>,
21    pub replicas: Option<u16>,
22    pub revision_history_limit: Option<u16>,
23    pub selector: LabelSelector,
24    pub service_name: String,
25    pub template: TemplateSpec<PodSpec>,
26    pub volume_claim_templates: Vec<TemplateSpec<PersistentVolumeClaim>>,
27    pub update_strategy: Option<StatefulSetUpdateStrategy>,
28}
29
30impl Spec for StatefulSetSpec {
31    type Status = StatefulSetStatus;
32    type Header = DefaultHeader;
33
34    fn metadata() -> &'static Crd {
35        &STATEFUL_API
36    }
37}
38
39#[derive(Deserialize, Serialize, Debug, Default, Clone)]
40#[serde(rename_all = "camelCase")]
41pub struct StatefulSetUpdateStrategy {
42    pub _type: String,
43    pub rolling_ipdate: Option<RollingUpdateStatefulSetStrategy>,
44}
45
46#[derive(Deserialize, Serialize, Debug, Default, Clone)]
47#[serde(rename_all = "camelCase")]
48pub struct RollingUpdateStatefulSetStrategy {
49    partition: u32,
50}
51
52#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
53pub enum PodMangementPolicy {
54    OrderedReady,
55    Parallel,
56}
57
58#[derive(Deserialize, Serialize, Debug, Clone)]
59#[serde(rename_all = "camelCase")]
60pub struct PersistentVolumeClaim {
61    pub access_modes: Vec<VolumeAccessMode>,
62    pub storage_class_name: String,
63    pub resources: ResourceRequirements,
64}
65
66#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
67pub enum VolumeAccessMode {
68    ReadWriteOnce,
69    ReadWrite,
70    ReadOnlyMany,
71}
72
73#[derive(Deserialize, Serialize, Debug, Clone)]
74pub struct ResourceRequirements {
75    pub requests: VolumeRequest,
76}
77
78#[derive(Deserialize, Serialize, Debug, Clone)]
79pub struct VolumeRequest {
80    pub storage: String,
81}
82
83#[derive(Deserialize, Serialize, Default, Debug, Clone)]
84#[serde(rename_all = "camelCase")]
85pub struct StatefulSetStatus {
86    pub replicas: u16,
87    pub collision_count: Option<u32>,
88    #[serde(default)]
89    pub conditions: Vec<StatefulSetCondition>,
90    pub current_replicas: Option<u16>,
91    pub current_revision: Option<String>,
92    pub observed_generation: Option<u32>,
93    pub ready_replicas: Option<u16>,
94    pub update_revision: Option<String>,
95    pub updated_replicas: Option<u16>,
96}
97
98impl Status for StatefulSetStatus {}
99
100#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
101pub enum StatusEnum {
102    True,
103    False,
104    Unknown,
105}
106
107#[derive(Deserialize, Serialize, Debug, Clone)]
108#[serde(rename_all = "camelCase")]
109pub struct StatefulSetCondition {
110    pub message: String,
111    pub reason: StatusEnum,
112    pub status: String,
113    #[serde(rename = "type")]
114    pub _type: String,
115}
116
117/*
118#[cfg(test)]
119mod test {
120
121    use serde_json;
122    use serde_json::json;
123
124    use super::LabelSelector;
125    use super::StatefulSetSpec;
126    use k8_diff::Changes;
127    use k8_metadata::cluster::ClusterSpec;
128    use k8_metadata::cluster::Configuration;
129    use k8_metadata::cluster::Cluster;
130    use k8_metadata::cluster::ClusterEndpoint;
131
132    #[test]
133    fn test_label_selector() {
134        let selector = LabelSelector::new_labels(vec![("app".to_owned(), "test".to_owned())]);
135
136        let maps = selector.match_labels;
137        assert_eq!(maps.len(), 1);
138        assert_eq!(maps.get("app").unwrap(), "test");
139    }
140
141    #[test]
142    fn test_cluster_to_stateful() {
143        let cluster = ClusterSpec {
144            cluster: Cluster {
145                replicas: Some(3),
146                rack: Some("rack1".to_string()),
147                public_endpoint: Some(ClusterEndpoint::new(9005)),
148                private_endpoint: Some(ClusterEndpoint::new(9006)),
149                controller_endpoint: Some(ClusterEndpoint::new(9004)),
150            },
151            configuration: Some(Configuration::default()),
152            env: None,
153        };
154
155        let stateful: StatefulSetSpec = (&cluster).into();
156        assert_eq!(stateful.replicas, Some(3));
157        let mut stateful2 = stateful.clone();
158        stateful2.replicas = Some(2);
159
160        let state1_json = serde_json::to_value(stateful).expect("json");
161        let state2_json = serde_json::to_value(stateful2).expect("json");
162        let diff = state1_json.diff(&state2_json).expect("diff");
163        let json_diff = serde_json::to_value(diff).unwrap();
164        assert_eq!(
165            json_diff,
166            json!({
167                "replicas": 2
168            })
169        );
170    }
171
172
173    /*
174    * TODO: make this as utility
175    use std::io::Read;
176    use std::fs::File;
177    use k8_metadata_core::metadata::ObjectMeta;
178    use k8_metadata_core::metadata::K8Obj;
179    use super::StatefulSetStatus;
180    use super::TemplateSpec;
181    use super::PodSpec;
182    use super::ContainerSpec;
183    use super::ContainerPortSpec;
184
185    #[test]
186    fn test_decode_statefulset()  {
187        let file_name = "/private/tmp/f1.json";
188
189        let mut f = File::open(file_name).expect("open failed");
190        let mut contents = String::new();
191        f.read_to_string(&mut contents).expect("read file");
192       // let st: StatefulSetSpec = serde_json::from_slice(&buffer).expect("error");
193        let st: K8Obj<StatefulSetSpec,StatefulSetStatus> = serde_json::from_str(&contents).expect("error");
194        println!("st: {:#?}",st);
195        assert!(true);
196    }
197    */
198
199}
200*/