openstack_sdk/api/compute/v2/server/
rebuild_21.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)]
37#[builder(setter(strip_option))]
38pub struct Personality<'a> {
39 #[serde(skip_serializing_if = "Option::is_none")]
40 #[builder(default, setter(into))]
41 pub(crate) contents: Option<Cow<'a, str>>,
42
43 #[serde(skip_serializing_if = "Option::is_none")]
44 #[builder(default, setter(into))]
45 pub(crate) path: Option<Cow<'a, str>>,
46}
47
48#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
50#[builder(setter(strip_option))]
51pub struct Rebuild<'a> {
52 #[serde(rename = "accessIPv4", skip_serializing_if = "Option::is_none")]
54 #[builder(default, setter(into))]
55 pub(crate) access_ipv4: Option<Cow<'a, str>>,
56
57 #[serde(rename = "accessIPv6", skip_serializing_if = "Option::is_none")]
59 #[builder(default, setter(into))]
60 pub(crate) access_ipv6: Option<Cow<'a, str>>,
61
62 #[serde(rename = "adminPass", skip_serializing_if = "Option::is_none")]
65 #[builder(default, setter(into))]
66 pub(crate) admin_pass: Option<Cow<'a, str>>,
67
68 #[serde(rename = "imageRef")]
78 #[builder(setter(into))]
79 pub(crate) image_ref: Cow<'a, str>,
80
81 #[serde(skip_serializing_if = "Option::is_none")]
84 #[builder(default, private, setter(into, name = "_metadata"))]
85 pub(crate) metadata: Option<BTreeMap<Cow<'a, str>, Cow<'a, str>>>,
86
87 #[serde(skip_serializing_if = "Option::is_none")]
89 #[builder(default, setter(into))]
90 pub(crate) name: Option<Cow<'a, str>>,
91
92 #[serde(rename = "OS-DCF:diskConfig", skip_serializing_if = "Option::is_none")]
109 #[builder(default)]
110 pub(crate) os_dcf_disk_config: Option<OsDcfDiskConfig>,
111
112 #[serde(skip_serializing_if = "Option::is_none")]
119 #[builder(default, setter(into))]
120 pub(crate) personality: Option<Vec<Personality<'a>>>,
121
122 #[serde(skip_serializing_if = "Option::is_none")]
131 #[builder(default, setter(into))]
132 pub(crate) preserve_ephemeral: Option<bool>,
133}
134
135impl<'a> RebuildBuilder<'a> {
136 pub fn metadata<I, K, V>(&mut self, iter: I) -> &mut Self
139 where
140 I: Iterator<Item = (K, V)>,
141 K: Into<Cow<'a, str>>,
142 V: Into<Cow<'a, str>>,
143 {
144 self.metadata
145 .get_or_insert(None)
146 .get_or_insert_with(BTreeMap::new)
147 .extend(iter.map(|(k, v)| (k.into(), v.into())));
148 self
149 }
150}
151
152#[derive(Builder, Debug, Clone)]
153#[builder(setter(strip_option))]
154pub struct Request<'a> {
155 #[builder(setter(into))]
157 pub(crate) rebuild: Rebuild<'a>,
158
159 #[builder(default, setter(into))]
161 id: Cow<'a, str>,
162
163 #[builder(setter(name = "_headers"), default, private)]
164 _headers: Option<HeaderMap>,
165}
166impl<'a> Request<'a> {
167 pub fn builder() -> RequestBuilder<'a> {
169 RequestBuilder::default()
170 }
171}
172
173impl<'a> RequestBuilder<'a> {
174 pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
176 where
177 K: Into<HeaderName>,
178 V: Into<HeaderValue>,
179 {
180 self._headers
181 .get_or_insert(None)
182 .get_or_insert_with(HeaderMap::new)
183 .insert(header_name.into(), header_value.into());
184 self
185 }
186
187 pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
189 where
190 I: Iterator<Item = T>,
191 T: Into<(Option<HeaderName>, HeaderValue)>,
192 {
193 self._headers
194 .get_or_insert(None)
195 .get_or_insert_with(HeaderMap::new)
196 .extend(iter.map(Into::into));
197 self
198 }
199}
200
201impl RestEndpoint for Request<'_> {
202 fn method(&self) -> http::Method {
203 http::Method::POST
204 }
205
206 fn endpoint(&self) -> Cow<'static, str> {
207 format!("servers/{id}/action", id = self.id.as_ref(),).into()
208 }
209
210 fn parameters(&self) -> QueryParams<'_> {
211 QueryParams::default()
212 }
213
214 fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
215 let mut params = JsonBodyParams::default();
216
217 params.push("rebuild", serde_json::to_value(&self.rebuild)?);
218
219 params.into_body()
220 }
221
222 fn service_type(&self) -> ServiceType {
223 ServiceType::Compute
224 }
225
226 fn response_key(&self) -> Option<Cow<'static, str>> {
227 None
228 }
229
230 fn request_headers(&self) -> Option<&HeaderMap> {
232 self._headers.as_ref()
233 }
234
235 fn api_version(&self) -> Option<ApiVersion> {
237 Some(ApiVersion::new(2, 1))
238 }
239}
240
241#[cfg(test)]
242mod tests {
243 use super::*;
244 #[cfg(feature = "sync")]
245 use crate::api::Query;
246 use crate::test::client::FakeOpenStackClient;
247 use crate::types::ServiceType;
248 use http::{HeaderName, HeaderValue};
249 use httpmock::MockServer;
250 use serde_json::json;
251
252 #[test]
253 fn test_service_type() {
254 assert_eq!(
255 Request::builder()
256 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
257 .build()
258 .unwrap()
259 .service_type(),
260 ServiceType::Compute
261 );
262 }
263
264 #[test]
265 fn test_response_key() {
266 assert!(Request::builder()
267 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
268 .build()
269 .unwrap()
270 .response_key()
271 .is_none())
272 }
273
274 #[cfg(feature = "sync")]
275 #[test]
276 fn endpoint() {
277 let server = MockServer::start();
278 let client = FakeOpenStackClient::new(server.base_url());
279 let mock = server.mock(|when, then| {
280 when.method(httpmock::Method::POST)
281 .path(format!("/servers/{id}/action", id = "id",));
282
283 then.status(200)
284 .header("content-type", "application/json")
285 .json_body(json!({ "dummy": {} }));
286 });
287
288 let endpoint = Request::builder()
289 .id("id")
290 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
291 .build()
292 .unwrap();
293 let _: serde_json::Value = endpoint.query(&client).unwrap();
294 mock.assert();
295 }
296
297 #[cfg(feature = "sync")]
298 #[test]
299 fn endpoint_headers() {
300 let server = MockServer::start();
301 let client = FakeOpenStackClient::new(server.base_url());
302 let mock = server.mock(|when, then| {
303 when.method(httpmock::Method::POST)
304 .path(format!("/servers/{id}/action", id = "id",))
305 .header("foo", "bar")
306 .header("not_foo", "not_bar");
307 then.status(200)
308 .header("content-type", "application/json")
309 .json_body(json!({ "dummy": {} }));
310 });
311
312 let endpoint = Request::builder()
313 .id("id")
314 .rebuild(RebuildBuilder::default().image_ref("foo").build().unwrap())
315 .headers(
316 [(
317 Some(HeaderName::from_static("foo")),
318 HeaderValue::from_static("bar"),
319 )]
320 .into_iter(),
321 )
322 .header(
323 HeaderName::from_static("not_foo"),
324 HeaderValue::from_static("not_bar"),
325 )
326 .build()
327 .unwrap();
328 let _: serde_json::Value = endpoint.query(&client).unwrap();
329 mock.assert();
330 }
331}