openstack_sdk/api/identity/v3/domain/config/group/
set.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//! Updates a domain group configuration.
19//!
20//! The API supports only the `identity` and `ldap` groups. If you try to set
21//! configuration options for other groups, this call fails with the
22//! `Forbidden (403)` response code.
23//!
24//! Relationship:
25//! `https://docs.openstack.org/api/openstack-identity/3/rel/domain_config_default`
26//!
27use 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    /// A `config` object.
40    #[builder(private, setter(into, name = "_config"))]
41    pub(crate) config: BTreeMap<Cow<'a, str>, BTreeMap<Cow<'a, str>, Value>>,
42
43    /// domain_id parameter for /v3/domains/{domain_id}/config/{group}/{option}
44    /// API
45    #[builder(default, setter(into))]
46    domain_id: Cow<'a, str>,
47
48    /// group parameter for /v3/domains/{domain_id}/config/{group}/{option} API
49    #[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    /// Create a builder for the endpoint.
57    pub fn builder() -> RequestBuilder<'a> {
58        RequestBuilder::default()
59    }
60}
61
62impl<'a> RequestBuilder<'a> {
63    /// A `config` object.
64    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    /// Add a single header to the Group.
84    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    /// Add multiple headers.
97    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    /// Returns headers to be set into the request
145    fn request_headers(&self) -> Option<&HeaderMap> {
146        self._headers.as_ref()
147    }
148
149    /// Returns required API version
150    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}