openstack_sdk/api/compute/v2/server/
rebuild_290.rs1use derive_builder::Builder;
19use http::{HeaderMap, HeaderName, HeaderValue};
20
21use crate::api::rest_endpoint_prelude::*;
22
23use serde::Deserialize;
24use serde::Serialize;
25use std::borrow::Cow;
26use std::collections::BTreeMap;
27
28#[derive(Debug, Deserialize, Clone, Serialize)]
29pub enum OsDcfDiskConfig {
30 #[serde(rename = "AUTO")]
31 Auto,
32 #[serde(rename = "MANUAL")]
33 Manual,
34}
35
36#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
38#[builder(setter(strip_option))]
39pub struct Rebuild<'a> {
40 #[serde(rename = "accessIPv4", skip_serializing_if = "Option::is_none")]
42 #[builder(default, setter(into))]
43 pub(crate) access_ipv4: Option<Cow<'a, str>>,
44
45 #[serde(rename = "accessIPv6", skip_serializing_if = "Option::is_none")]
47 #[builder(default, setter(into))]
48 pub(crate) access_ipv6: Option<Cow<'a, str>>,
49
50 #[serde(rename = "adminPass", skip_serializing_if = "Option::is_none")]
53 #[builder(default, setter(into))]
54 pub(crate) admin_pass: Option<Cow<'a, str>>,
55
56 #[serde(skip_serializing_if = "Option::is_none")]
61 #[builder(default, setter(into))]
62 pub(crate) description: Option<Option<Cow<'a, str>>>,
63
64 #[serde(skip_serializing_if = "Option::is_none")]
77 #[builder(default, setter(into))]
78 pub(crate) hostname: Option<Cow<'a, str>>,
79
80 #[serde(rename = "imageRef")]
90 #[builder(setter(into))]
91 pub(crate) image_ref: Cow<'a, str>,
92
93 #[serde(skip_serializing_if = "Option::is_none")]
106 #[builder(default, setter(into))]
107 pub(crate) key_name: Option<Option<Cow<'a, str>>>,
108
109 #[serde(skip_serializing_if = "Option::is_none")]
112 #[builder(default, private, setter(into, name = "_metadata"))]
113 pub(crate) metadata: Option<BTreeMap<Cow<'a, str>, Cow<'a, str>>>,
114
115 #[serde(skip_serializing_if = "Option::is_none")]
117 #[builder(default, setter(into))]
118 pub(crate) name: Option<Cow<'a, str>>,
119
120 #[serde(rename = "OS-DCF:diskConfig", skip_serializing_if = "Option::is_none")]
137 #[builder(default)]
138 pub(crate) os_dcf_disk_config: Option<OsDcfDiskConfig>,
139
140 #[serde(skip_serializing_if = "Option::is_none")]
149 #[builder(default, setter(into))]
150 pub(crate) preserve_ephemeral: Option<bool>,
151
152 #[serde(skip_serializing_if = "Option::is_none")]
163 #[builder(default, setter(into))]
164 pub(crate) trusted_image_certificates: Option<Vec<Cow<'a, str>>>,
165
166 #[serde(skip_serializing_if = "Option::is_none")]
172 #[builder(default, setter(into))]
173 pub(crate) user_data: Option<Option<Cow<'a, str>>>,
174}
175
176impl<'a> RebuildBuilder<'a> {
177 pub fn metadata<I, K, V>(&mut self, iter: I) -> &mut Self
180 where
181 I: Iterator<Item = (K, V)>,
182 K: Into<Cow<'a, str>>,
183 V: Into<Cow<'a, str>>,
184 {
185 self.metadata
186 .get_or_insert(None)
187 .get_or_insert_with(BTreeMap::new)
188 .extend(iter.map(|(k, v)| (k.into(), v.into())));
189 self
190 }
191}
192
193#[derive(Builder, Debug, Clone)]
194#[builder(setter(strip_option))]
195pub struct Request<'a> {
196 #[builder(setter(into))]
198 pub(crate) rebuild: Rebuild<'a>,
199
200 #[builder(default, setter(into))]
202 id: Cow<'a, str>,
203
204 #[builder(setter(name = "_headers"), default, private)]
205 _headers: Option<HeaderMap>,
206}
207impl<'a> Request<'a> {
208 pub fn builder() -> RequestBuilder<'a> {
210 RequestBuilder::default()
211 }
212}
213
214impl<'a> RequestBuilder<'a> {
215 pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
217 where
218 K: Into<HeaderName>,
219 V: Into<HeaderValue>,
220 {
221 self._headers
222 .get_or_insert(None)
223 .get_or_insert_with(HeaderMap::new)
224 .insert(header_name.into(), header_value.into());
225 self
226 }
227
228 pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
230 where
231 I: Iterator<Item = T>,
232 T: Into<(Option<HeaderName>, HeaderValue)>,
233 {
234 self._headers
235 .get_or_insert(None)
236 .get_or_insert_with(HeaderMap::new)
237 .extend(iter.map(Into::into));
238 self
239 }
240}
241
242impl RestEndpoint for Request<'_> {
243 fn method(&self) -> http::Method {
244 http::Method::POST
245 }
246
247 fn endpoint(&self) -> Cow<'static, str> {
248 format!("servers/{id}/action", id = self.id.as_ref(),).into()
249 }
250
251 fn parameters(&self) -> QueryParams<'_> {
252 QueryParams::default()
253 }
254
255 fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
256 let mut params = JsonBodyParams::default();
257
258 params.push("rebuild", serde_json::to_value(&self.rebuild)?);
259
260 params.into_body()
261 }
262
263 fn service_type(&self) -> ServiceType {
264 ServiceType::Compute
265 }
266
267 fn response_key(&self) -> Option<Cow<'static, str>> {
268 None
269 }
270
271 fn request_headers(&self) -> Option<&HeaderMap> {
273 self._headers.as_ref()
274 }
275
276 fn api_version(&self) -> Option<ApiVersion> {
278 Some(ApiVersion::new(2, 90))
279 }
280}
281
282#[cfg(test)]
283mod tests {
284 use super::*;
285 #[cfg(feature = "sync")]
286 use crate::api::Query;
287 use crate::test::client::FakeOpenStackClient;
288 use crate::types::ServiceType;
289 use http::{HeaderName, HeaderValue};
290 use httpmock::MockServer;
291 use serde_json::json;
292
293 #[test]
294 fn test_service_type() {
295 assert_eq!(
296 Request::builder()
297 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
298 .build()
299 .unwrap()
300 .service_type(),
301 ServiceType::Compute
302 );
303 }
304
305 #[test]
306 fn test_response_key() {
307 assert!(Request::builder()
308 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
309 .build()
310 .unwrap()
311 .response_key()
312 .is_none())
313 }
314
315 #[cfg(feature = "sync")]
316 #[test]
317 fn endpoint() {
318 let server = MockServer::start();
319 let client = FakeOpenStackClient::new(server.base_url());
320 let mock = server.mock(|when, then| {
321 when.method(httpmock::Method::POST)
322 .path(format!("/servers/{id}/action", id = "id",));
323
324 then.status(200)
325 .header("content-type", "application/json")
326 .json_body(json!({ "dummy": {} }));
327 });
328
329 let endpoint = Request::builder()
330 .id("id")
331 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
332 .build()
333 .unwrap();
334 let _: serde_json::Value = endpoint.query(&client).unwrap();
335 mock.assert();
336 }
337
338 #[cfg(feature = "sync")]
339 #[test]
340 fn endpoint_headers() {
341 let server = MockServer::start();
342 let client = FakeOpenStackClient::new(server.base_url());
343 let mock = server.mock(|when, then| {
344 when.method(httpmock::Method::POST)
345 .path(format!("/servers/{id}/action", id = "id",))
346 .header("foo", "bar")
347 .header("not_foo", "not_bar");
348 then.status(200)
349 .header("content-type", "application/json")
350 .json_body(json!({ "dummy": {} }));
351 });
352
353 let endpoint = Request::builder()
354 .id("id")
355 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
356 .headers(
357 [(
358 Some(HeaderName::from_static("foo")),
359 HeaderValue::from_static("bar"),
360 )]
361 .into_iter(),
362 )
363 .header(
364 HeaderName::from_static("not_foo"),
365 HeaderValue::from_static("not_bar"),
366 )
367 .build()
368 .unwrap();
369 let _: serde_json::Value = endpoint.query(&client).unwrap();
370 mock.assert();
371 }
372}