openstack_sdk_load_balancer/v2/l7policy/rule/
create.rs1use derive_builder::Builder;
46use http::{HeaderMap, HeaderName, HeaderValue};
47
48use openstack_sdk_core::api::rest_endpoint_prelude::*;
49
50use serde::Deserialize;
51use serde::Serialize;
52use std::borrow::Cow;
53
54#[derive(Debug, Deserialize, Clone, Serialize)]
55pub enum CompareType {
56 #[serde(rename = "CONTAINS")]
57 Contains,
58 #[serde(rename = "ENDS_WITH")]
59 EndsWith,
60 #[serde(rename = "EQUAL_TO")]
61 EqualTo,
62 #[serde(rename = "REGEX")]
63 Regex,
64 #[serde(rename = "STARTS_WITH")]
65 StartsWith,
66}
67
68#[derive(Debug, Deserialize, Clone, Serialize)]
69pub enum Type {
70 #[serde(rename = "COOKIE")]
71 Cookie,
72 #[serde(rename = "FILE_TYPE")]
73 FileType,
74 #[serde(rename = "HEADER")]
75 Header,
76 #[serde(rename = "HOST_NAME")]
77 HostName,
78 #[serde(rename = "PATH")]
79 Path,
80 #[serde(rename = "SSL_CONN_HAS_CERT")]
81 SslConnHasCert,
82 #[serde(rename = "SSL_DN_FIELD")]
83 SslDnField,
84 #[serde(rename = "SSL_VERIFY_RESULT")]
85 SslVerifyResult,
86}
87
88#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
90#[builder(setter(strip_option))]
91pub struct Rule<'a> {
92 #[serde(skip_serializing_if = "Option::is_none")]
95 #[builder(default, setter(into))]
96 pub(crate) admin_state_up: Option<bool>,
97
98 #[serde()]
101 #[builder()]
102 pub(crate) compare_type: CompareType,
103
104 #[serde(skip_serializing_if = "Option::is_none")]
107 #[builder(default, setter(into))]
108 pub(crate) invert: Option<bool>,
109
110 #[serde(skip_serializing_if = "Option::is_none")]
113 #[builder(default, setter(into))]
114 pub(crate) key: Option<Cow<'a, str>>,
115
116 #[serde(skip_serializing_if = "Option::is_none")]
118 #[builder(default, setter(into))]
119 pub(crate) project_id: Option<Cow<'a, str>>,
120
121 #[serde(skip_serializing_if = "Option::is_none")]
125 #[builder(default, setter(into))]
126 pub(crate) tags: Option<Vec<Cow<'a, str>>>,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
129 #[builder(default, setter(into))]
130 pub(crate) tenant_id: Option<Cow<'a, str>>,
131
132 #[serde(rename = "type")]
135 #[builder()]
136 pub(crate) _type: Type,
137
138 #[serde()]
141 #[builder(setter(into))]
142 pub(crate) value: Cow<'a, str>,
143}
144
145#[derive(Builder, Debug, Clone)]
146#[builder(setter(strip_option))]
147pub struct Request<'a> {
148 #[builder(setter(into))]
150 pub(crate) rule: Rule<'a>,
151
152 #[builder(default, setter(into))]
155 l7policy_id: Cow<'a, str>,
156
157 #[builder(setter(name = "_headers"), default, private)]
158 _headers: Option<HeaderMap>,
159}
160impl<'a> Request<'a> {
161 pub fn builder() -> RequestBuilder<'a> {
163 RequestBuilder::default()
164 }
165}
166
167impl<'a> RequestBuilder<'a> {
168 pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
170 where
171 K: Into<HeaderName>,
172 V: Into<HeaderValue>,
173 {
174 self._headers
175 .get_or_insert(None)
176 .get_or_insert_with(HeaderMap::new)
177 .insert(header_name.into(), header_value.into());
178 self
179 }
180
181 pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
183 where
184 I: Iterator<Item = T>,
185 T: Into<(Option<HeaderName>, HeaderValue)>,
186 {
187 self._headers
188 .get_or_insert(None)
189 .get_or_insert_with(HeaderMap::new)
190 .extend(iter.map(Into::into));
191 self
192 }
193}
194
195impl RestEndpoint for Request<'_> {
196 fn method(&self) -> http::Method {
197 http::Method::POST
198 }
199
200 fn endpoint(&self) -> Cow<'static, str> {
201 format!(
202 "lbaas/l7policies/{l7policy_id}/rules",
203 l7policy_id = self.l7policy_id.as_ref(),
204 )
205 .into()
206 }
207
208 fn parameters(&self) -> QueryParams<'_> {
209 QueryParams::default()
210 }
211
212 fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
213 let mut params = JsonBodyParams::default();
214
215 params.push("rule", serde_json::to_value(&self.rule)?);
216
217 params.into_body()
218 }
219
220 fn service_type(&self) -> ServiceType {
221 ServiceType::LoadBalancer
222 }
223
224 fn response_key(&self) -> Option<Cow<'static, str>> {
225 Some("rule".into())
226 }
227
228 fn request_headers(&self) -> Option<&HeaderMap> {
230 self._headers.as_ref()
231 }
232
233 fn api_version(&self) -> Option<ApiVersion> {
235 Some(ApiVersion::new(2, 0))
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242 use http::{HeaderName, HeaderValue};
243 use httpmock::MockServer;
244 #[cfg(feature = "sync")]
245 use openstack_sdk_core::api::Query;
246 use openstack_sdk_core::test::client::FakeOpenStackClient;
247 use openstack_sdk_core::types::ServiceType;
248 use serde_json::json;
249
250 #[test]
251 fn test_service_type() {
252 assert_eq!(
253 Request::builder()
254 .rule(
255 RuleBuilder::default()
256 ._type(Type::Cookie)
257 .compare_type(CompareType::Contains)
258 .value("foo")
259 .build()
260 .unwrap()
261 )
262 .build()
263 .unwrap()
264 .service_type(),
265 ServiceType::LoadBalancer
266 );
267 }
268
269 #[test]
270 fn test_response_key() {
271 assert_eq!(
272 Request::builder()
273 .rule(
274 RuleBuilder::default()
275 ._type(Type::Cookie)
276 .compare_type(CompareType::Contains)
277 .value("foo")
278 .build()
279 .unwrap()
280 )
281 .build()
282 .unwrap()
283 .response_key()
284 .unwrap(),
285 "rule"
286 );
287 }
288
289 #[cfg(feature = "sync")]
290 #[test]
291 fn endpoint() {
292 let server = MockServer::start();
293 let client = FakeOpenStackClient::new(server.base_url());
294 let mock = server.mock(|when, then| {
295 when.method(httpmock::Method::POST).path(format!(
296 "/lbaas/l7policies/{l7policy_id}/rules",
297 l7policy_id = "l7policy_id",
298 ));
299
300 then.status(200)
301 .header("content-type", "application/json")
302 .json_body(json!({ "rule": {} }));
303 });
304
305 let endpoint = Request::builder()
306 .l7policy_id("l7policy_id")
307 .rule(
308 RuleBuilder::default()
309 ._type(Type::Cookie)
310 .compare_type(CompareType::Contains)
311 .value("foo")
312 .build()
313 .unwrap(),
314 )
315 .build()
316 .unwrap();
317 let _: serde_json::Value = endpoint.query(&client).unwrap();
318 mock.assert();
319 }
320
321 #[cfg(feature = "sync")]
322 #[test]
323 fn endpoint_headers() {
324 let server = MockServer::start();
325 let client = FakeOpenStackClient::new(server.base_url());
326 let mock = server.mock(|when, then| {
327 when.method(httpmock::Method::POST)
328 .path(format!(
329 "/lbaas/l7policies/{l7policy_id}/rules",
330 l7policy_id = "l7policy_id",
331 ))
332 .header("foo", "bar")
333 .header("not_foo", "not_bar");
334 then.status(200)
335 .header("content-type", "application/json")
336 .json_body(json!({ "rule": {} }));
337 });
338
339 let endpoint = Request::builder()
340 .l7policy_id("l7policy_id")
341 .rule(
342 RuleBuilder::default()
343 ._type(Type::Cookie)
344 .compare_type(CompareType::Contains)
345 .value("foo")
346 .build()
347 .unwrap(),
348 )
349 .headers(
350 [(
351 Some(HeaderName::from_static("foo")),
352 HeaderValue::from_static("bar"),
353 )]
354 .into_iter(),
355 )
356 .header(
357 HeaderName::from_static("not_foo"),
358 HeaderValue::from_static("not_bar"),
359 )
360 .build()
361 .unwrap();
362 let _: serde_json::Value = endpoint.query(&client).unwrap();
363 mock.assert();
364 }
365}