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