openstack_sdk/api/compute/v2/server/volume_attachment/
create_249.rs1use derive_builder::Builder;
26use http::{HeaderMap, HeaderName, HeaderValue};
27
28use crate::api::rest_endpoint_prelude::*;
29
30use serde::Deserialize;
31use serde::Serialize;
32use std::borrow::Cow;
33
34#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
37#[builder(setter(strip_option))]
38pub struct VolumeAttachment<'a> {
39 #[serde(skip_serializing_if = "Option::is_none")]
46 #[builder(default, setter(into))]
47 pub(crate) device: Option<Option<Cow<'a, str>>>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
61 #[builder(default, setter(into))]
62 pub(crate) tag: Option<Cow<'a, str>>,
63
64 #[serde(rename = "volumeId")]
66 #[builder(setter(into))]
67 pub(crate) volume_id: Cow<'a, str>,
68}
69
70#[derive(Builder, Debug, Clone)]
71#[builder(setter(strip_option))]
72pub struct Request<'a> {
73 #[builder(setter(into))]
76 pub(crate) volume_attachment: VolumeAttachment<'a>,
77
78 #[builder(default, setter(into))]
81 server_id: Cow<'a, str>,
82
83 #[builder(setter(name = "_headers"), default, private)]
84 _headers: Option<HeaderMap>,
85}
86impl<'a> Request<'a> {
87 pub fn builder() -> RequestBuilder<'a> {
89 RequestBuilder::default()
90 }
91}
92
93impl<'a> RequestBuilder<'a> {
94 pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
96 where
97 K: Into<HeaderName>,
98 V: Into<HeaderValue>,
99 {
100 self._headers
101 .get_or_insert(None)
102 .get_or_insert_with(HeaderMap::new)
103 .insert(header_name.into(), header_value.into());
104 self
105 }
106
107 pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
109 where
110 I: Iterator<Item = T>,
111 T: Into<(Option<HeaderName>, HeaderValue)>,
112 {
113 self._headers
114 .get_or_insert(None)
115 .get_or_insert_with(HeaderMap::new)
116 .extend(iter.map(Into::into));
117 self
118 }
119}
120
121impl RestEndpoint for Request<'_> {
122 fn method(&self) -> http::Method {
123 http::Method::POST
124 }
125
126 fn endpoint(&self) -> Cow<'static, str> {
127 format!(
128 "servers/{server_id}/os-volume_attachments",
129 server_id = self.server_id.as_ref(),
130 )
131 .into()
132 }
133
134 fn parameters(&self) -> QueryParams<'_> {
135 QueryParams::default()
136 }
137
138 fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
139 let mut params = JsonBodyParams::default();
140
141 params.push(
142 "volumeAttachment",
143 serde_json::to_value(&self.volume_attachment)?,
144 );
145
146 params.into_body()
147 }
148
149 fn service_type(&self) -> ServiceType {
150 ServiceType::Compute
151 }
152
153 fn response_key(&self) -> Option<Cow<'static, str>> {
154 Some("volumeAttachment".into())
155 }
156
157 fn request_headers(&self) -> Option<&HeaderMap> {
159 self._headers.as_ref()
160 }
161
162 fn api_version(&self) -> Option<ApiVersion> {
164 Some(ApiVersion::new(2, 49))
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171 #[cfg(feature = "sync")]
172 use crate::api::Query;
173 use crate::test::client::FakeOpenStackClient;
174 use crate::types::ServiceType;
175 use http::{HeaderName, HeaderValue};
176 use httpmock::MockServer;
177 use serde_json::json;
178
179 #[test]
180 fn test_service_type() {
181 assert_eq!(
182 Request::builder()
183 .volume_attachment(
184 VolumeAttachmentBuilder::default()
185 .volume_id("foo")
186 .build()
187 .unwrap()
188 )
189 .build()
190 .unwrap()
191 .service_type(),
192 ServiceType::Compute
193 );
194 }
195
196 #[test]
197 fn test_response_key() {
198 assert_eq!(
199 Request::builder()
200 .volume_attachment(
201 VolumeAttachmentBuilder::default()
202 .volume_id("foo")
203 .build()
204 .unwrap()
205 )
206 .build()
207 .unwrap()
208 .response_key()
209 .unwrap(),
210 "volumeAttachment"
211 );
212 }
213
214 #[cfg(feature = "sync")]
215 #[test]
216 fn endpoint() {
217 let server = MockServer::start();
218 let client = FakeOpenStackClient::new(server.base_url());
219 let mock = server.mock(|when, then| {
220 when.method(httpmock::Method::POST).path(format!(
221 "/servers/{server_id}/os-volume_attachments",
222 server_id = "server_id",
223 ));
224
225 then.status(200)
226 .header("content-type", "application/json")
227 .json_body(json!({ "volumeAttachment": {} }));
228 });
229
230 let endpoint = Request::builder()
231 .server_id("server_id")
232 .volume_attachment(
233 VolumeAttachmentBuilder::default()
234 .volume_id("foo")
235 .build()
236 .unwrap(),
237 )
238 .build()
239 .unwrap();
240 let _: serde_json::Value = endpoint.query(&client).unwrap();
241 mock.assert();
242 }
243
244 #[cfg(feature = "sync")]
245 #[test]
246 fn endpoint_headers() {
247 let server = MockServer::start();
248 let client = FakeOpenStackClient::new(server.base_url());
249 let mock = server.mock(|when, then| {
250 when.method(httpmock::Method::POST)
251 .path(format!(
252 "/servers/{server_id}/os-volume_attachments",
253 server_id = "server_id",
254 ))
255 .header("foo", "bar")
256 .header("not_foo", "not_bar");
257 then.status(200)
258 .header("content-type", "application/json")
259 .json_body(json!({ "volumeAttachment": {} }));
260 });
261
262 let endpoint = Request::builder()
263 .server_id("server_id")
264 .volume_attachment(
265 VolumeAttachmentBuilder::default()
266 .volume_id("foo")
267 .build()
268 .unwrap(),
269 )
270 .headers(
271 [(
272 Some(HeaderName::from_static("foo")),
273 HeaderValue::from_static("bar"),
274 )]
275 .into_iter(),
276 )
277 .header(
278 HeaderName::from_static("not_foo"),
279 HeaderValue::from_static("not_bar"),
280 )
281 .build()
282 .unwrap();
283 let _: serde_json::Value = endpoint.query(&client).unwrap();
284 mock.assert();
285 }
286}