openstack_sdk_identity/v3/role/
create.rs1use derive_builder::Builder;
24use http::{HeaderMap, HeaderName, HeaderValue};
25
26use openstack_sdk_core::api::rest_endpoint_prelude::*;
27
28use serde::Deserialize;
29use serde::Serialize;
30use serde_json::Value;
31use std::borrow::Cow;
32use std::collections::BTreeMap;
33
34#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
37#[builder(setter(strip_option))]
38pub struct Options {
39 #[serde(skip_serializing_if = "Option::is_none")]
40 #[builder(default, setter(into))]
41 pub(crate) immutable: Option<bool>,
42}
43
44#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
46#[builder(setter(strip_option))]
47pub struct Role<'a> {
48 #[serde(skip_serializing_if = "Option::is_none")]
50 #[builder(default, setter(into))]
51 pub(crate) description: Option<Option<Cow<'a, str>>>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 #[builder(default, setter(into))]
56 pub(crate) domain_id: Option<Option<Cow<'a, str>>>,
57
58 #[serde()]
60 #[builder(setter(into))]
61 pub(crate) name: Cow<'a, str>,
62
63 #[serde(skip_serializing_if = "Option::is_none")]
66 #[builder(default, setter(into))]
67 pub(crate) options: Option<Options>,
68
69 #[builder(setter(name = "_properties"), default, private)]
70 #[serde(flatten)]
71 _properties: BTreeMap<Cow<'a, str>, Value>,
72}
73
74impl<'a> RoleBuilder<'a> {
75 pub fn properties<I, K, V>(&mut self, iter: I) -> &mut Self
76 where
77 I: Iterator<Item = (K, V)>,
78 K: Into<Cow<'a, str>>,
79 V: Into<Value>,
80 {
81 self._properties
82 .get_or_insert_with(BTreeMap::new)
83 .extend(iter.map(|(k, v)| (k.into(), v.into())));
84 self
85 }
86}
87
88#[derive(Builder, Debug, Clone)]
89#[builder(setter(strip_option))]
90pub struct Request<'a> {
91 #[builder(setter(into))]
93 pub(crate) role: Role<'a>,
94
95 #[builder(setter(name = "_headers"), default, private)]
96 _headers: Option<HeaderMap>,
97}
98impl<'a> Request<'a> {
99 pub fn builder() -> RequestBuilder<'a> {
101 RequestBuilder::default()
102 }
103}
104
105impl<'a> RequestBuilder<'a> {
106 pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
108 where
109 K: Into<HeaderName>,
110 V: Into<HeaderValue>,
111 {
112 self._headers
113 .get_or_insert(None)
114 .get_or_insert_with(HeaderMap::new)
115 .insert(header_name.into(), header_value.into());
116 self
117 }
118
119 pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
121 where
122 I: Iterator<Item = T>,
123 T: Into<(Option<HeaderName>, HeaderValue)>,
124 {
125 self._headers
126 .get_or_insert(None)
127 .get_or_insert_with(HeaderMap::new)
128 .extend(iter.map(Into::into));
129 self
130 }
131}
132
133impl RestEndpoint for Request<'_> {
134 fn method(&self) -> http::Method {
135 http::Method::POST
136 }
137
138 fn endpoint(&self) -> Cow<'static, str> {
139 "roles".to_string().into()
140 }
141
142 fn parameters(&self) -> QueryParams<'_> {
143 QueryParams::default()
144 }
145
146 fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
147 let mut params = JsonBodyParams::default();
148
149 params.push("role", serde_json::to_value(&self.role)?);
150
151 params.into_body()
152 }
153
154 fn service_type(&self) -> ServiceType {
155 ServiceType::Identity
156 }
157
158 fn response_key(&self) -> Option<Cow<'static, str>> {
159 Some("role".into())
160 }
161
162 fn request_headers(&self) -> Option<&HeaderMap> {
164 self._headers.as_ref()
165 }
166
167 fn api_version(&self) -> Option<ApiVersion> {
169 Some(ApiVersion::new(3, 0))
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176 use http::{HeaderName, HeaderValue};
177 use httpmock::MockServer;
178 #[cfg(feature = "sync")]
179 use openstack_sdk_core::api::Query;
180 use openstack_sdk_core::test::client::FakeOpenStackClient;
181 use openstack_sdk_core::types::ServiceType;
182 use serde_json::json;
183
184 #[test]
185 fn test_service_type() {
186 assert_eq!(
187 Request::builder()
188 .role(RoleBuilder::default().name("foo").build().unwrap())
189 .build()
190 .unwrap()
191 .service_type(),
192 ServiceType::Identity
193 );
194 }
195
196 #[test]
197 fn test_response_key() {
198 assert_eq!(
199 Request::builder()
200 .role(RoleBuilder::default().name("foo").build().unwrap())
201 .build()
202 .unwrap()
203 .response_key()
204 .unwrap(),
205 "role"
206 );
207 }
208
209 #[cfg(feature = "sync")]
210 #[test]
211 fn endpoint() {
212 let server = MockServer::start();
213 let client = FakeOpenStackClient::new(server.base_url());
214 let mock = server.mock(|when, then| {
215 when.method(httpmock::Method::POST)
216 .path("/roles".to_string());
217
218 then.status(200)
219 .header("content-type", "application/json")
220 .json_body(json!({ "role": {} }));
221 });
222
223 let endpoint = Request::builder()
224 .role(RoleBuilder::default().name("foo").build().unwrap())
225 .build()
226 .unwrap();
227 let _: serde_json::Value = endpoint.query(&client).unwrap();
228 mock.assert();
229 }
230
231 #[cfg(feature = "sync")]
232 #[test]
233 fn endpoint_headers() {
234 let server = MockServer::start();
235 let client = FakeOpenStackClient::new(server.base_url());
236 let mock = server.mock(|when, then| {
237 when.method(httpmock::Method::POST)
238 .path("/roles".to_string())
239 .header("foo", "bar")
240 .header("not_foo", "not_bar");
241 then.status(200)
242 .header("content-type", "application/json")
243 .json_body(json!({ "role": {} }));
244 });
245
246 let endpoint = Request::builder()
247 .role(RoleBuilder::default().name("foo").build().unwrap())
248 .headers(
249 [(
250 Some(HeaderName::from_static("foo")),
251 HeaderValue::from_static("bar"),
252 )]
253 .into_iter(),
254 )
255 .header(
256 HeaderName::from_static("not_foo"),
257 HeaderValue::from_static("not_bar"),
258 )
259 .build()
260 .unwrap();
261 let _: serde_json::Value = endpoint.query(&client).unwrap();
262 mock.assert();
263 }
264}