openstack_sdk/api/identity/v3/role/
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 role.
19//!
20//! Relationship:
21//! `https://docs.openstack.org/api/openstack-identity/3/rel/role`
22//!
23use derive_builder::Builder;
24use http::{HeaderMap, HeaderName, HeaderValue};
25
26use crate::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/// The resource options for the role. Available resource options are
35/// `immutable`.
36#[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/// A `role` object
45#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
46#[builder(setter(strip_option))]
47pub struct Role<'a> {
48    /// The new role description.
49    #[serde(skip_serializing_if = "Option::is_none")]
50    #[builder(default, setter(into))]
51    pub(crate) description: Option<Option<Cow<'a, str>>>,
52
53    /// The ID of the domain.
54    #[serde(skip_serializing_if = "Option::is_none")]
55    #[builder(default, setter(into))]
56    pub(crate) domain_id: Option<Option<Cow<'a, str>>>,
57
58    /// The new role name.
59    #[serde(skip_serializing_if = "Option::is_none")]
60    #[builder(default, setter(into))]
61    pub(crate) name: Option<Cow<'a, str>>,
62
63    /// The resource options for the role. Available resource options are
64    /// `immutable`.
65    #[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    /// A `role` object
92    #[builder(setter(into))]
93    pub(crate) role: Role<'a>,
94
95    /// role_id parameter for /v3/roles/{role_id} API
96    #[builder(default, setter(into))]
97    id: Cow<'a, str>,
98
99    #[builder(setter(name = "_headers"), default, private)]
100    _headers: Option<HeaderMap>,
101}
102impl<'a> Request<'a> {
103    /// Create a builder for the endpoint.
104    pub fn builder() -> RequestBuilder<'a> {
105        RequestBuilder::default()
106    }
107}
108
109impl<'a> RequestBuilder<'a> {
110    /// Add a single header to the Role.
111    pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
112    where
113        K: Into<HeaderName>,
114        V: Into<HeaderValue>,
115    {
116        self._headers
117            .get_or_insert(None)
118            .get_or_insert_with(HeaderMap::new)
119            .insert(header_name.into(), header_value.into());
120        self
121    }
122
123    /// Add multiple headers.
124    pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
125    where
126        I: Iterator<Item = T>,
127        T: Into<(Option<HeaderName>, HeaderValue)>,
128    {
129        self._headers
130            .get_or_insert(None)
131            .get_or_insert_with(HeaderMap::new)
132            .extend(iter.map(Into::into));
133        self
134    }
135}
136
137impl RestEndpoint for Request<'_> {
138    fn method(&self) -> http::Method {
139        http::Method::PATCH
140    }
141
142    fn endpoint(&self) -> Cow<'static, str> {
143        format!("roles/{id}", id = self.id.as_ref(),).into()
144    }
145
146    fn parameters(&self) -> QueryParams<'_> {
147        QueryParams::default()
148    }
149
150    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
151        let mut params = JsonBodyParams::default();
152
153        params.push("role", serde_json::to_value(&self.role)?);
154
155        params.into_body()
156    }
157
158    fn service_type(&self) -> ServiceType {
159        ServiceType::Identity
160    }
161
162    fn response_key(&self) -> Option<Cow<'static, str>> {
163        Some("role".into())
164    }
165
166    /// Returns headers to be set into the request
167    fn request_headers(&self) -> Option<&HeaderMap> {
168        self._headers.as_ref()
169    }
170
171    /// Returns required API version
172    fn api_version(&self) -> Option<ApiVersion> {
173        Some(ApiVersion::new(3, 0))
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    #[cfg(feature = "sync")]
181    use crate::api::Query;
182    use crate::test::client::FakeOpenStackClient;
183    use crate::types::ServiceType;
184    use http::{HeaderName, HeaderValue};
185    use httpmock::MockServer;
186    use serde_json::json;
187
188    #[test]
189    fn test_service_type() {
190        assert_eq!(
191            Request::builder()
192                .role(RoleBuilder::default().build().unwrap())
193                .build()
194                .unwrap()
195                .service_type(),
196            ServiceType::Identity
197        );
198    }
199
200    #[test]
201    fn test_response_key() {
202        assert_eq!(
203            Request::builder()
204                .role(RoleBuilder::default().build().unwrap())
205                .build()
206                .unwrap()
207                .response_key()
208                .unwrap(),
209            "role"
210        );
211    }
212
213    #[cfg(feature = "sync")]
214    #[test]
215    fn endpoint() {
216        let server = MockServer::start();
217        let client = FakeOpenStackClient::new(server.base_url());
218        let mock = server.mock(|when, then| {
219            when.method(httpmock::Method::PATCH)
220                .path(format!("/roles/{id}", id = "id",));
221
222            then.status(200)
223                .header("content-type", "application/json")
224                .json_body(json!({ "role": {} }));
225        });
226
227        let endpoint = Request::builder()
228            .id("id")
229            .role(RoleBuilder::default().build().unwrap())
230            .build()
231            .unwrap();
232        let _: serde_json::Value = endpoint.query(&client).unwrap();
233        mock.assert();
234    }
235
236    #[cfg(feature = "sync")]
237    #[test]
238    fn endpoint_headers() {
239        let server = MockServer::start();
240        let client = FakeOpenStackClient::new(server.base_url());
241        let mock = server.mock(|when, then| {
242            when.method(httpmock::Method::PATCH)
243                .path(format!("/roles/{id}", id = "id",))
244                .header("foo", "bar")
245                .header("not_foo", "not_bar");
246            then.status(200)
247                .header("content-type", "application/json")
248                .json_body(json!({ "role": {} }));
249        });
250
251        let endpoint = Request::builder()
252            .id("id")
253            .role(RoleBuilder::default().build().unwrap())
254            .headers(
255                [(
256                    Some(HeaderName::from_static("foo")),
257                    HeaderValue::from_static("bar"),
258                )]
259                .into_iter(),
260            )
261            .header(
262                HeaderName::from_static("not_foo"),
263                HeaderValue::from_static("not_bar"),
264            )
265            .build()
266            .unwrap();
267        let _: serde_json::Value = endpoint.query(&client).unwrap();
268        mock.assert();
269    }
270}