openstack_sdk/
types.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//! Types of the SDK
16
17#![allow(dead_code)]
18use secrecy::{ExposeSecret, SecretString};
19use std::fmt;
20
21pub mod api_version;
22pub mod common;
23pub mod compute;
24pub mod identity;
25
26use futures::io::AsyncRead;
27use futures::io::Error;
28use std::pin::Pin;
29use std::task::{Context, Poll};
30
31pub use crate::types::api_version::ApiVersion;
32pub use common::{IdAndName, NameOrId};
33
34/// Supported Service Types
35#[derive(Debug, Clone, Eq, PartialEq)]
36pub enum ServiceType {
37    BlockStorage,
38    Compute,
39    ContainerInfrastructureManagement,
40    Dns,
41    Image,
42    Identity,
43    LoadBalancer,
44    Network,
45    ObjectStore,
46    Placement,
47    Other(String),
48}
49
50impl fmt::Display for ServiceType {
51    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52        match self {
53            ServiceType::BlockStorage => write!(f, "block-storage"),
54            ServiceType::Compute => write!(f, "compute"),
55            ServiceType::ContainerInfrastructureManagement => {
56                write!(f, "container-infrastructure-management")
57            }
58            ServiceType::Dns => write!(f, "dns"),
59            ServiceType::Image => write!(f, "image"),
60            ServiceType::Identity => write!(f, "identity"),
61            ServiceType::LoadBalancer => write!(f, "load-balancer"),
62            ServiceType::Network => write!(f, "network"),
63            ServiceType::ObjectStore => write!(f, "object-store"),
64            ServiceType::Placement => write!(f, "placement"),
65            ServiceType::Other(x) => write!(f, "{x}"),
66        }
67    }
68}
69
70impl From<&str> for ServiceType {
71    fn from(val: &str) -> ServiceType {
72        match val {
73            "block-storage" => ServiceType::BlockStorage,
74            "compute" => ServiceType::Compute,
75            "container-infrastructure-management" => ServiceType::ContainerInfrastructureManagement,
76            "dns" => ServiceType::Dns,
77            "identity" => ServiceType::Identity,
78            "image" => ServiceType::Image,
79            "load-balancer" => ServiceType::LoadBalancer,
80            "network" => ServiceType::Network,
81            "object-store" => ServiceType::ObjectStore,
82            _ => ServiceType::Other(val.into()),
83        }
84    }
85}
86
87/// A wrapper around `AsyncRead` trait allowing returning HTTP response body as something
88/// implementing `AsyncRead`.
89/// Returning `impl AsyncRead` would be the best option, but since
90/// we need to return it from inside a trait function it is
91/// currently not possible in Rust to do so and the only way is to
92/// `return Box<dyn AsyncRead>`. This is however also challenging,
93/// since it is not possible to invoke tokio `compat` function to
94/// convert `futures::AsyncRead` into `tokio::io::AsyncRead`. In order
95/// to deal with that this wrapper is created and something
96/// implementing `AsyncRead` can be passed into it and further used
97/// as anything implementing `AsyncRead` on its own.
98pub struct BoxedAsyncRead {
99    reader: Pin<Box<dyn AsyncRead>>,
100}
101unsafe impl Send for BoxedAsyncRead {}
102unsafe impl Sync for BoxedAsyncRead {}
103
104impl BoxedAsyncRead {
105    pub fn new(reader: impl AsyncRead + Send + Sync + 'static) -> Self {
106        Self {
107            reader: Box::pin(reader),
108        }
109    }
110}
111
112impl fmt::Debug for BoxedAsyncRead {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        write!(f, "_data_")
115    }
116}
117
118impl AsyncRead for BoxedAsyncRead {
119    fn poll_read(
120        mut self: Pin<&mut Self>,
121        cx: &mut Context<'_>,
122        buf: &mut [u8],
123    ) -> Poll<Result<usize, Error>> {
124        self.reader.as_mut().poll_read(cx, buf)
125    }
126}
127
128/// Status of the resource
129#[derive(Debug, Default, PartialEq)]
130pub enum EntryStatus {
131    /// Normal status
132    #[default]
133    Normal,
134    /// Any Error
135    Error,
136    /// Some Action is in progress
137    Pending,
138    /// Inactive
139    Inactive,
140}
141
142impl From<Option<&String>> for EntryStatus {
143    fn from(input: Option<&String>) -> EntryStatus {
144        match input {
145            Some(val) => match val.to_lowercase().as_str() {
146                // Statuses treated as an error
147                "degraded" | "error" | "error_deleting" | "error_backing-up"
148                | "error_restoring" | "error_extending" | "killed" => Self::Error,
149                // Statuses treated as an currently in progress
150                "attaching" | "backing-up" | "build" | "building" | "creating" | "detaching"
151                | "downloading" | "extending" | "importing" | "pending" | "queued"
152                | "restoring" | "restoring-backup" | "saving" | "uploading" => Self::Pending,
153                // inactive
154                "available" | "deleted" | "no_monitor" | "offline" | "reserved" | "shutoff" => {
155                    Self::Inactive
156                }
157                _ => Self::Normal,
158            },
159            None => Self::Normal,
160        }
161    }
162}
163
164/// Serialize `SecretString` as string
165pub fn serialize_sensitive_optional_string<S>(
166    value: &Option<SecretString>,
167    serializer: S,
168) -> Result<S::Ok, S::Error>
169where
170    S: serde::Serializer,
171{
172    match value {
173        Some(val) => serializer.serialize_str(val.expose_secret()),
174        None => serializer.serialize_none(),
175    }
176}
177
178/// Serialize `Option<SecretString>` as string
179pub fn serialize_sensitive_string<S>(value: &SecretString, serializer: S) -> Result<S::Ok, S::Error>
180where
181    S: serde::Serializer,
182{
183    serializer.serialize_str(value.expose_secret())
184}
185
186#[cfg(test)]
187mod tests {
188    use super::*;
189
190    #[test]
191    fn test_entry_status() {
192        assert_eq!(
193            EntryStatus::Error,
194            EntryStatus::from(Some(&String::from("DEGRADED")))
195        );
196        assert_eq!(
197            EntryStatus::Error,
198            EntryStatus::from(Some(&String::from("error")))
199        );
200        assert_eq!(
201            EntryStatus::Error,
202            EntryStatus::from(Some(&String::from("error_backing-up")))
203        );
204        assert_eq!(
205            EntryStatus::Error,
206            EntryStatus::from(Some(&String::from("error_deleting")))
207        );
208        assert_eq!(
209            EntryStatus::Error,
210            EntryStatus::from(Some(&String::from("error_restoring")))
211        );
212        assert_eq!(
213            EntryStatus::Error,
214            EntryStatus::from(Some(&String::from("error_extending")))
215        );
216        assert_eq!(
217            EntryStatus::Error,
218            EntryStatus::from(Some(&String::from("killed")))
219        );
220        assert_eq!(
221            EntryStatus::Pending,
222            EntryStatus::from(Some(&String::from("attaching")))
223        );
224        assert_eq!(
225            EntryStatus::Pending,
226            EntryStatus::from(Some(&String::from("backing-up")))
227        );
228        assert_eq!(
229            EntryStatus::Pending,
230            EntryStatus::from(Some(&String::from("build")))
231        );
232        assert_eq!(
233            EntryStatus::Pending,
234            EntryStatus::from(Some(&String::from("building")))
235        );
236        assert_eq!(
237            EntryStatus::Pending,
238            EntryStatus::from(Some(&String::from("creating")))
239        );
240        assert_eq!(
241            EntryStatus::Pending,
242            EntryStatus::from(Some(&String::from("detaching")))
243        );
244        assert_eq!(
245            EntryStatus::Pending,
246            EntryStatus::from(Some(&String::from("downloading")))
247        );
248        assert_eq!(
249            EntryStatus::Pending,
250            EntryStatus::from(Some(&String::from("extending")))
251        );
252        assert_eq!(
253            EntryStatus::Pending,
254            EntryStatus::from(Some(&String::from("importing")))
255        );
256        assert_eq!(
257            EntryStatus::Pending,
258            EntryStatus::from(Some(&String::from("pending")))
259        );
260        assert_eq!(
261            EntryStatus::Pending,
262            EntryStatus::from(Some(&String::from("queued")))
263        );
264        assert_eq!(
265            EntryStatus::Pending,
266            EntryStatus::from(Some(&String::from("restoring")))
267        );
268        assert_eq!(
269            EntryStatus::Pending,
270            EntryStatus::from(Some(&String::from("restoring-backup")))
271        );
272        assert_eq!(
273            EntryStatus::Pending,
274            EntryStatus::from(Some(&String::from("saving")))
275        );
276        assert_eq!(
277            EntryStatus::Pending,
278            EntryStatus::from(Some(&String::from("uploading")))
279        );
280        assert_eq!(
281            EntryStatus::Inactive,
282            EntryStatus::from(Some(&String::from("available")))
283        );
284        assert_eq!(
285            EntryStatus::Inactive,
286            EntryStatus::from(Some(&String::from("deleted")))
287        );
288        assert_eq!(
289            EntryStatus::Inactive,
290            EntryStatus::from(Some(&String::from("no_monitor")))
291        );
292        assert_eq!(
293            EntryStatus::Inactive,
294            EntryStatus::from(Some(&String::from("offline")))
295        );
296        assert_eq!(
297            EntryStatus::Inactive,
298            EntryStatus::from(Some(&String::from("reserved")))
299        );
300        assert_eq!(
301            EntryStatus::Inactive,
302            EntryStatus::from(Some(&String::from("shutoff")))
303        );
304        assert_eq!(
305            EntryStatus::Normal,
306            EntryStatus::from(Some(&String::from("foobar")))
307        );
308        assert_eq!(EntryStatus::Normal, EntryStatus::from(None));
309    }
310}