1pub 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)]
22pub struct LibpodPingInfo {
24 pub api_version: String,
26 pub libpod_api_version: String,
28 pub libpod_buildah_version: String,
30 pub buildkit_version: Option<String>,
32 pub cache_control: String,
34 pub docker_experimental: bool,
36 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)]
188pub 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}