kube_core/conversion/
types.rs1use crate::{Status, TypeMeta};
2use serde::{Deserialize, Deserializer, Serialize};
3use thiserror::Error;
4
5pub const META_KIND: &str = "ConversionReview";
7pub const META_API_VERSION_V1: &str = "apiextensions.k8s.io/v1";
9
10#[derive(Debug, Error)]
11#[error("request missing in ConversionReview")]
12pub struct ConvertConversionReviewError;
14
15#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
17pub struct ConversionReview {
18 #[serde(flatten)]
20 pub types: TypeMeta,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub request: Option<ConversionRequest>,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 #[serde(default)]
27 pub response: Option<ConversionResponse>,
28}
29
30#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
32pub struct ConversionRequest {
33 #[serde(skip)]
38 pub types: Option<TypeMeta>,
39 pub uid: String,
41 #[serde(rename = "desiredAPIVersion")]
43 pub desired_api_version: String,
44 pub objects: Vec<serde_json::Value>,
50}
51
52impl ConversionRequest {
53 pub fn from_review(review: ConversionReview) -> Result<Self, ConvertConversionReviewError> {
55 ConversionRequest::try_from(review)
56 }
57}
58
59impl TryFrom<ConversionReview> for ConversionRequest {
60 type Error = ConvertConversionReviewError;
61
62 fn try_from(review: ConversionReview) -> Result<Self, Self::Error> {
63 match review.request {
64 Some(mut req) => {
65 req.types = Some(review.types);
66 Ok(req)
67 }
68 None => Err(ConvertConversionReviewError),
69 }
70 }
71}
72
73#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
75pub struct ConversionResponse {
76 #[serde(skip)]
81 pub types: Option<TypeMeta>,
82 pub uid: String,
84 pub result: Status,
90 #[serde(rename = "convertedObjects")]
95 #[serde(deserialize_with = "parse_converted_objects")]
96 pub converted_objects: Vec<serde_json::Value>,
97}
98
99fn parse_converted_objects<'de, D>(de: D) -> Result<Vec<serde_json::Value>, D::Error>
100where
101 D: Deserializer<'de>,
102{
103 #[derive(Deserialize)]
104 #[serde(untagged)]
105 enum Helper {
106 List(Vec<serde_json::Value>),
107 Null(()),
108 }
109
110 let h: Helper = Helper::deserialize(de)?;
111 let res = match h {
112 Helper::List(l) => l,
113 Helper::Null(()) => Vec::new(),
114 };
115 Ok(res)
116}
117
118impl ConversionResponse {
119 pub fn for_request(request: ConversionRequest) -> Self {
125 ConversionResponse::from(request)
126 }
127
128 pub fn success(mut self, converted_objects: Vec<serde_json::Value>) -> Self {
132 self.result = Status::success();
133 self.converted_objects = converted_objects;
134 self
135 }
136
137 pub fn failure(mut self, status: Status) -> Self {
142 self.result = status;
143 self
144 }
145
146 pub fn invalid(status: Status) -> Self {
151 ConversionResponse {
152 types: None,
153 uid: String::new(),
154 result: status,
155 converted_objects: Vec::new(),
156 }
157 }
158
159 pub fn into_review(self) -> ConversionReview {
161 self.into()
162 }
163}
164
165impl From<ConversionRequest> for ConversionResponse {
166 fn from(request: ConversionRequest) -> Self {
167 ConversionResponse {
168 types: request.types,
169 uid: request.uid,
170 result: Status {
171 status: None,
172 code: 0,
173 message: String::new(),
174 metadata: None,
175 reason: String::new(),
176 details: None,
177 },
178 converted_objects: Vec::new(),
179 }
180 }
181}
182
183impl From<ConversionResponse> for ConversionReview {
184 fn from(mut response: ConversionResponse) -> Self {
185 ConversionReview {
186 types: response.types.take().unwrap_or_else(|| {
187 TypeMeta {
189 api_version: META_API_VERSION_V1.to_string(),
190 kind: META_KIND.to_string(),
191 }
192 }),
193 request: None,
194 response: Some(response),
195 }
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::{ConversionRequest, ConversionResponse};
202
203 #[test]
204 fn simple_request_parses() {
205 let data = include_str!("./test_data/simple.json");
207 let review = serde_json::from_str(data).unwrap();
209 let req = ConversionRequest::from_review(review).unwrap();
210 let res = ConversionResponse::for_request(req);
211 let _ = res.into_review();
212 }
213}