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