openstack_sdk/api/compute/v2/flavor/
create_21.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//
15// WARNING: This file is automatically generated from OpenAPI schema using
16// `openstack-codegenerator`.
17
18//! Creates a flavor.
19//!
20//! Creating a flavor is typically only available to administrators of a cloud
21//! because this has implications for scheduling efficiently in the cloud.
22//!
23//! Normal response codes: 200
24//!
25//! Error response codes: badRequest(400), unauthorized(401), forbidden(403),
26//! conflict(409)
27//!
28use derive_builder::Builder;
29use http::{HeaderMap, HeaderName, HeaderValue};
30
31use crate::api::rest_endpoint_prelude::*;
32
33use serde::Deserialize;
34use serde::Serialize;
35use std::borrow::Cow;
36
37/// The ID and links for the flavor for your server instance. A flavor is a
38/// combination of memory, disk size, and CPUs.
39#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
40#[builder(setter(strip_option))]
41pub struct Flavor<'a> {
42    /// The size of a dedicated swap disk that will be allocated, in MiB. If 0
43    /// (the default), no dedicated swap disk will be created.
44    #[serde()]
45    #[builder(setter(into))]
46    pub(crate) disk: i32,
47
48    /// Only alphanumeric characters with hyphen ‘-’, underscore ‘\_’, spaces
49    /// and dots ‘.’ are permitted. If an ID is not provided, then a default
50    /// UUID will be assigned.
51    #[serde(skip_serializing_if = "Option::is_none")]
52    #[builder(default, setter(into))]
53    pub(crate) id: Option<Option<Cow<'a, str>>>,
54
55    /// The display name of a flavor.
56    #[serde()]
57    #[builder(setter(into))]
58    pub(crate) name: Cow<'a, str>,
59
60    /// Whether the flavor is public (available to all projects) or scoped to a
61    /// set of projects. Default is True if not specified.
62    #[serde(
63        rename = "os-flavor-access:is_public",
64        skip_serializing_if = "Option::is_none"
65    )]
66    #[builder(default, setter(into))]
67    pub(crate) os_flavor_access_is_public: Option<bool>,
68
69    /// The size of a dedicated swap disk that will be allocated, in MiB. If 0
70    /// (the default), no dedicated swap disk will be created.
71    #[serde(
72        rename = "OS-FLV-EXT-DATA:ephemeral",
73        skip_serializing_if = "Option::is_none"
74    )]
75    #[builder(default, setter(into))]
76    pub(crate) os_flv_ext_data_ephemeral: Option<i32>,
77
78    /// The number of virtual CPUs that will be allocated to the server.
79    #[serde()]
80    #[builder(setter(into))]
81    pub(crate) ram: i32,
82
83    /// The receive / transmit factor (as a float) that will be set on ports if
84    /// the network backend supports the QOS extension. Otherwise it will be
85    /// ignored. It defaults to 1.0.
86    #[serde(skip_serializing_if = "Option::is_none")]
87    #[builder(default, setter(into))]
88    pub(crate) rxtx_factor: Option<Cow<'a, str>>,
89
90    /// The size of a dedicated swap disk that will be allocated, in MiB. If 0
91    /// (the default), no dedicated swap disk will be created.
92    #[serde(skip_serializing_if = "Option::is_none")]
93    #[builder(default, setter(into))]
94    pub(crate) swap: Option<i32>,
95
96    /// The number of virtual CPUs that will be allocated to the server.
97    #[serde()]
98    #[builder(setter(into))]
99    pub(crate) vcpus: i32,
100}
101
102#[derive(Builder, Debug, Clone)]
103#[builder(setter(strip_option))]
104pub struct Request<'a> {
105    /// The ID and links for the flavor for your server instance. A flavor is a
106    /// combination of memory, disk size, and CPUs.
107    #[builder(setter(into))]
108    pub(crate) flavor: Flavor<'a>,
109
110    #[builder(setter(name = "_headers"), default, private)]
111    _headers: Option<HeaderMap>,
112}
113impl<'a> Request<'a> {
114    /// Create a builder for the endpoint.
115    pub fn builder() -> RequestBuilder<'a> {
116        RequestBuilder::default()
117    }
118}
119
120impl<'a> RequestBuilder<'a> {
121    /// Add a single header to the Flavor.
122    pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
123    where
124        K: Into<HeaderName>,
125        V: Into<HeaderValue>,
126    {
127        self._headers
128            .get_or_insert(None)
129            .get_or_insert_with(HeaderMap::new)
130            .insert(header_name.into(), header_value.into());
131        self
132    }
133
134    /// Add multiple headers.
135    pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
136    where
137        I: Iterator<Item = T>,
138        T: Into<(Option<HeaderName>, HeaderValue)>,
139    {
140        self._headers
141            .get_or_insert(None)
142            .get_or_insert_with(HeaderMap::new)
143            .extend(iter.map(Into::into));
144        self
145    }
146}
147
148impl RestEndpoint for Request<'_> {
149    fn method(&self) -> http::Method {
150        http::Method::POST
151    }
152
153    fn endpoint(&self) -> Cow<'static, str> {
154        "flavors".to_string().into()
155    }
156
157    fn parameters(&self) -> QueryParams<'_> {
158        QueryParams::default()
159    }
160
161    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
162        let mut params = JsonBodyParams::default();
163
164        params.push("flavor", serde_json::to_value(&self.flavor)?);
165
166        params.into_body()
167    }
168
169    fn service_type(&self) -> ServiceType {
170        ServiceType::Compute
171    }
172
173    fn response_key(&self) -> Option<Cow<'static, str>> {
174        Some("flavor".into())
175    }
176
177    /// Returns headers to be set into the request
178    fn request_headers(&self) -> Option<&HeaderMap> {
179        self._headers.as_ref()
180    }
181
182    /// Returns required API version
183    fn api_version(&self) -> Option<ApiVersion> {
184        Some(ApiVersion::new(2, 1))
185    }
186}
187
188#[cfg(test)]
189mod tests {
190    use super::*;
191    #[cfg(feature = "sync")]
192    use crate::api::Query;
193    use crate::test::client::FakeOpenStackClient;
194    use crate::types::ServiceType;
195    use http::{HeaderName, HeaderValue};
196    use httpmock::MockServer;
197    use serde_json::json;
198
199    #[test]
200    fn test_service_type() {
201        assert_eq!(
202            Request::builder()
203                .flavor(
204                    FlavorBuilder::default()
205                        .disk(123)
206                        .name("foo")
207                        .ram(123)
208                        .vcpus(123)
209                        .build()
210                        .unwrap()
211                )
212                .build()
213                .unwrap()
214                .service_type(),
215            ServiceType::Compute
216        );
217    }
218
219    #[test]
220    fn test_response_key() {
221        assert_eq!(
222            Request::builder()
223                .flavor(
224                    FlavorBuilder::default()
225                        .disk(123)
226                        .name("foo")
227                        .ram(123)
228                        .vcpus(123)
229                        .build()
230                        .unwrap()
231                )
232                .build()
233                .unwrap()
234                .response_key()
235                .unwrap(),
236            "flavor"
237        );
238    }
239
240    #[cfg(feature = "sync")]
241    #[test]
242    fn endpoint() {
243        let server = MockServer::start();
244        let client = FakeOpenStackClient::new(server.base_url());
245        let mock = server.mock(|when, then| {
246            when.method(httpmock::Method::POST)
247                .path("/flavors".to_string());
248
249            then.status(200)
250                .header("content-type", "application/json")
251                .json_body(json!({ "flavor": {} }));
252        });
253
254        let endpoint = Request::builder()
255            .flavor(
256                FlavorBuilder::default()
257                    .disk(123)
258                    .name("foo")
259                    .ram(123)
260                    .vcpus(123)
261                    .build()
262                    .unwrap(),
263            )
264            .build()
265            .unwrap();
266        let _: serde_json::Value = endpoint.query(&client).unwrap();
267        mock.assert();
268    }
269
270    #[cfg(feature = "sync")]
271    #[test]
272    fn endpoint_headers() {
273        let server = MockServer::start();
274        let client = FakeOpenStackClient::new(server.base_url());
275        let mock = server.mock(|when, then| {
276            when.method(httpmock::Method::POST)
277                .path("/flavors".to_string())
278                .header("foo", "bar")
279                .header("not_foo", "not_bar");
280            then.status(200)
281                .header("content-type", "application/json")
282                .json_body(json!({ "flavor": {} }));
283        });
284
285        let endpoint = Request::builder()
286            .flavor(
287                FlavorBuilder::default()
288                    .disk(123)
289                    .name("foo")
290                    .ram(123)
291                    .vcpus(123)
292                    .build()
293                    .unwrap(),
294            )
295            .headers(
296                [(
297                    Some(HeaderName::from_static("foo")),
298                    HeaderValue::from_static("bar"),
299                )]
300                .into_iter(),
301            )
302            .header(
303                HeaderName::from_static("not_foo"),
304                HeaderValue::from_static("not_bar"),
305            )
306            .build()
307            .unwrap();
308        let _: serde_json::Value = endpoint.query(&client).unwrap();
309        mock.assert();
310    }
311}