openstack_sdk/api/network/v2/security_group/
create.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//! Creates an OpenStack Networking security group.
19//!
20//! This operation creates a security group with default security group rules
21//! for the IPv4 and IPv6 ether types.
22//!
23//! Normal response codes: 201
24//!
25//! Error response codes: 400, 401, 409
26//!
27use derive_builder::Builder;
28use http::{HeaderMap, HeaderName, HeaderValue};
29
30use crate::api::rest_endpoint_prelude::*;
31
32use serde::Deserialize;
33use serde::Serialize;
34use std::borrow::Cow;
35
36/// A `security_group` object.
37#[derive(Builder, Debug, Deserialize, Clone, Serialize)]
38#[builder(setter(strip_option))]
39pub struct SecurityGroup<'a> {
40    /// A human-readable description for the resource. Default is an empty
41    /// string.
42    #[serde(skip_serializing_if = "Option::is_none")]
43    #[builder(default, setter(into))]
44    pub(crate) description: Option<Cow<'a, str>>,
45
46    /// Human-readable name of the resource.
47    #[serde(skip_serializing_if = "Option::is_none")]
48    #[builder(default, setter(into))]
49    pub(crate) name: Option<Cow<'a, str>>,
50
51    /// Indicates if the security group is stateful or stateless.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    #[builder(default, setter(into))]
54    pub(crate) stateful: Option<bool>,
55
56    /// The ID of the project.
57    #[serde(skip_serializing_if = "Option::is_none")]
58    #[builder(default, setter(into))]
59    pub(crate) tenant_id: Option<Cow<'a, str>>,
60}
61
62#[derive(Builder, Debug, Clone)]
63#[builder(setter(strip_option))]
64pub struct Request<'a> {
65    /// A `security_group` object.
66    #[builder(setter(into))]
67    pub(crate) security_group: SecurityGroup<'a>,
68
69    #[builder(setter(name = "_headers"), default, private)]
70    _headers: Option<HeaderMap>,
71}
72impl<'a> Request<'a> {
73    /// Create a builder for the endpoint.
74    pub fn builder() -> RequestBuilder<'a> {
75        RequestBuilder::default()
76    }
77}
78
79impl<'a> RequestBuilder<'a> {
80    /// Add a single header to the Security_Group.
81    pub fn header<K, V>(&mut self, header_name: K, header_value: V) -> &mut Self
82    where
83        K: Into<HeaderName>,
84        V: Into<HeaderValue>,
85    {
86        self._headers
87            .get_or_insert(None)
88            .get_or_insert_with(HeaderMap::new)
89            .insert(header_name.into(), header_value.into());
90        self
91    }
92
93    /// Add multiple headers.
94    pub fn headers<I, T>(&mut self, iter: I) -> &mut Self
95    where
96        I: Iterator<Item = T>,
97        T: Into<(Option<HeaderName>, HeaderValue)>,
98    {
99        self._headers
100            .get_or_insert(None)
101            .get_or_insert_with(HeaderMap::new)
102            .extend(iter.map(Into::into));
103        self
104    }
105}
106
107impl RestEndpoint for Request<'_> {
108    fn method(&self) -> http::Method {
109        http::Method::POST
110    }
111
112    fn endpoint(&self) -> Cow<'static, str> {
113        "security-groups".to_string().into()
114    }
115
116    fn parameters(&self) -> QueryParams<'_> {
117        QueryParams::default()
118    }
119
120    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
121        let mut params = JsonBodyParams::default();
122
123        params.push(
124            "security_group",
125            serde_json::to_value(&self.security_group)?,
126        );
127
128        params.into_body()
129    }
130
131    fn service_type(&self) -> ServiceType {
132        ServiceType::Network
133    }
134
135    fn response_key(&self) -> Option<Cow<'static, str>> {
136        Some("security_group".into())
137    }
138
139    /// Returns headers to be set into the request
140    fn request_headers(&self) -> Option<&HeaderMap> {
141        self._headers.as_ref()
142    }
143
144    /// Returns required API version
145    fn api_version(&self) -> Option<ApiVersion> {
146        Some(ApiVersion::new(2, 0))
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153    #[cfg(feature = "sync")]
154    use crate::api::Query;
155    use crate::test::client::FakeOpenStackClient;
156    use crate::types::ServiceType;
157    use http::{HeaderName, HeaderValue};
158    use httpmock::MockServer;
159    use serde_json::json;
160
161    #[test]
162    fn test_service_type() {
163        assert_eq!(
164            Request::builder()
165                .security_group(SecurityGroupBuilder::default().build().unwrap())
166                .build()
167                .unwrap()
168                .service_type(),
169            ServiceType::Network
170        );
171    }
172
173    #[test]
174    fn test_response_key() {
175        assert_eq!(
176            Request::builder()
177                .security_group(SecurityGroupBuilder::default().build().unwrap())
178                .build()
179                .unwrap()
180                .response_key()
181                .unwrap(),
182            "security_group"
183        );
184    }
185
186    #[cfg(feature = "sync")]
187    #[test]
188    fn endpoint() {
189        let server = MockServer::start();
190        let client = FakeOpenStackClient::new(server.base_url());
191        let mock = server.mock(|when, then| {
192            when.method(httpmock::Method::POST)
193                .path("/security-groups".to_string());
194
195            then.status(200)
196                .header("content-type", "application/json")
197                .json_body(json!({ "security_group": {} }));
198        });
199
200        let endpoint = Request::builder()
201            .security_group(SecurityGroupBuilder::default().build().unwrap())
202            .build()
203            .unwrap();
204        let _: serde_json::Value = endpoint.query(&client).unwrap();
205        mock.assert();
206    }
207
208    #[cfg(feature = "sync")]
209    #[test]
210    fn endpoint_headers() {
211        let server = MockServer::start();
212        let client = FakeOpenStackClient::new(server.base_url());
213        let mock = server.mock(|when, then| {
214            when.method(httpmock::Method::POST)
215                .path("/security-groups".to_string())
216                .header("foo", "bar")
217                .header("not_foo", "not_bar");
218            then.status(200)
219                .header("content-type", "application/json")
220                .json_body(json!({ "security_group": {} }));
221        });
222
223        let endpoint = Request::builder()
224            .security_group(SecurityGroupBuilder::default().build().unwrap())
225            .headers(
226                [(
227                    Some(HeaderName::from_static("foo")),
228                    HeaderValue::from_static("bar"),
229                )]
230                .into_iter(),
231            )
232            .header(
233                HeaderName::from_static("not_foo"),
234                HeaderValue::from_static("not_bar"),
235            )
236            .build()
237            .unwrap();
238        let _: serde_json::Value = endpoint.query(&client).unwrap();
239        mock.assert();
240    }
241}