podman_api/
models.rs

1//! Models generated from libpod swagger spec
2
3pub use podman_api_stubs::models::*;
4
5use crate::{Error, Result};
6
7#[cfg(feature = "chrono")]
8use {
9    chrono::{DateTime, Utc},
10    containers_api::datetime::*,
11};
12
13use crate::conn::hyper::header::HeaderMap;
14use serde::{Deserialize, Serialize};
15use std::collections::HashMap;
16use std::fmt;
17use std::string::ToString;
18
19pub type Attributes = HashMap<String, String>;
20
21#[derive(Serialize, Debug)]
22/// Data returned from /ping endpoint by libpod
23pub struct LibpodPingInfo {
24    /// Max compatibility API Version the server supports
25    pub api_version: String,
26    /// Max Podman API Version the server supports. Available if service is backed by Podman, therefore may be used to determine if talking to Podman engine or another engine
27    pub libpod_api_version: String,
28    /// Default version of libpod image builder. Available if service is backed by Podman, therefore may be used to determine if talking to Podman engine or another engine
29    pub libpod_buildah_version: String,
30    /// Default version of docker image builder
31    pub buildkit_version: Option<String>,
32    /// Always no-cache
33    pub cache_control: String,
34    /// If the server is running with experimental mode enabled, always true
35    pub docker_experimental: bool,
36    /// Always no-cache
37    pub pragma: String,
38}
39
40impl TryFrom<&HeaderMap> for LibpodPingInfo {
41    type Error = Error;
42
43    fn try_from(value: &HeaderMap) -> Result<Self> {
44        macro_rules! extract_str {
45            ($id:literal) => {{
46                if let Some(val) = value.get($id) {
47                    val.to_str().map(ToString::to_string).map_err(|e| {
48                        Error::InvalidResponse(format!(
49                            "failed to convert header to string - {}",
50                            e
51                        ))
52                    })?
53                } else {
54                    return Err(Error::InvalidResponse(format!(
55                        "expected `{}` field in headers",
56                        $id
57                    )));
58                }
59            }};
60        }
61
62        Ok(LibpodPingInfo {
63            api_version: extract_str!("api-version"),
64            libpod_api_version: extract_str!("libpod-api-version"),
65            buildkit_version: value
66                .get("buildkit-version")
67                .and_then(|v| v.to_str().map(ToString::to_string).ok()),
68            docker_experimental: extract_str!("docker-experimental").parse().map_err(|e| {
69                Error::InvalidResponse(format!("expected header value to be bool - {e}"))
70            })?,
71            cache_control: extract_str!("cache-control"),
72            pragma: extract_str!("pragma"),
73            libpod_buildah_version: extract_str!("libpod-buildah-version"),
74        })
75    }
76}
77
78#[derive(Clone, Debug, Serialize, Deserialize)]
79pub struct Event {
80    #[serde(rename = "Type")]
81    pub typ: String,
82    #[serde(rename = "Action")]
83    pub action: String,
84    #[serde(rename = "Actor")]
85    pub actor: Actor,
86    pub status: Option<String>,
87    pub id: Option<String>,
88    pub from: Option<String>,
89    #[cfg(feature = "chrono")]
90    #[serde(deserialize_with = "datetime_from_unix_timestamp")]
91    pub time: DateTime<Utc>,
92    #[cfg(not(feature = "chrono"))]
93    pub time: u64,
94    #[cfg(feature = "chrono")]
95    #[serde(deserialize_with = "datetime_from_nano_timestamp", rename = "timeNano")]
96    pub time_nano: DateTime<Utc>,
97    #[cfg(not(feature = "chrono"))]
98    #[serde(rename = "timeNano")]
99    pub time_nano: u64,
100}
101
102#[derive(Clone, Debug, Serialize, Deserialize)]
103pub struct Actor {
104    #[serde(rename = "ID")]
105    pub id: String,
106    #[serde(rename = "Attributes")]
107    pub attributes: Attributes,
108}
109
110#[derive(Clone, Debug, Serialize, Deserialize)]
111#[serde(rename_all = "lowercase")]
112pub enum ContainerStatus {
113    Created,
114    Configured,
115    Restarting,
116    Running,
117    Removing,
118    Paused,
119    Exited,
120    Dead,
121}
122
123impl AsRef<str> for ContainerStatus {
124    fn as_ref(&self) -> &str {
125        use ContainerStatus::*;
126        match &self {
127            Created => "created",
128            Configured => "configured",
129            Restarting => "restarting",
130            Running => "running",
131            Removing => "removing",
132            Paused => "paused",
133            Exited => "exited",
134            Dead => "dead",
135        }
136    }
137}
138
139#[derive(Clone, Debug, Serialize, Deserialize)]
140#[serde(rename_all = "lowercase")]
141pub enum ContainerHealth {
142    Starting,
143    Healthy,
144    Unhealthy,
145    None,
146}
147
148impl AsRef<str> for ContainerHealth {
149    fn as_ref(&self) -> &str {
150        use ContainerHealth::*;
151        match &self {
152            Starting => "starting",
153            Healthy => "healthy",
154            Unhealthy => "unhealthy",
155            None => "none",
156        }
157    }
158}
159
160#[derive(Clone, Debug, Serialize, Deserialize)]
161#[serde(rename_all = "lowercase")]
162pub enum PodStatus {
163    Created,
164    Dead,
165    Degraded,
166    Exited,
167    Paused,
168    Running,
169    Stopped,
170}
171
172impl AsRef<str> for PodStatus {
173    fn as_ref(&self) -> &str {
174        use PodStatus::*;
175        match &self {
176            Created => "created",
177            Dead => "dead",
178            Degraded => "degraded",
179            Exited => "exited",
180            Paused => "paused",
181            Running => "running",
182            Stopped => "stopped",
183        }
184    }
185}
186
187#[derive(Clone, Debug, Serialize)]
188// Actual type used by ContainerCreate mount parameter.
189//
190// See: https://github.com/containers/podman/issues/13717
191pub struct ContainerMount {
192    #[serde(skip_serializing_if = "Option::is_none")]
193    pub destination: Option<String>,
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub options: Option<Vec<String>>,
196    #[serde(skip_serializing_if = "Option::is_none")]
197    pub source: Option<String>,
198    #[serde(rename = "type")]
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub _type: Option<String>,
201    #[serde(rename = "UIDMappings")]
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub uid_mappings: Option<Vec<IdMap>>,
204    #[serde(rename = "GIDMappings")]
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub gid_mappings: Option<Vec<IdMap>>,
207}
208
209#[derive(Clone, Debug, Serialize, Deserialize)]
210pub struct JsonErrorDetail {
211    #[serde(skip_serializing_if = "Option::is_none")]
212    message: Option<String>,
213}
214
215#[derive(Clone, Debug, Serialize, Deserialize)]
216pub struct JsonError {
217    #[serde(rename = "errorDetail")]
218    error_detail: Option<JsonErrorDetail>,
219    error: Option<String>,
220}
221
222impl std::error::Error for JsonError {}
223
224impl fmt::Display for JsonError {
225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226        let error = self.error.as_deref().unwrap_or_default();
227        let detail = self
228            .error_detail
229            .as_ref()
230            .and_then(|e| e.message.as_deref())
231            .unwrap_or_default();
232
233        write!(
234            f,
235            "{}{}{}",
236            error,
237            if !error.is_empty() { "-" } else { "" },
238            detail
239        )
240    }
241}