1use std::path::PathBuf;
6use thiserror::Error;
7
8#[derive(Debug, Error)]
10pub enum ZLayerError {
11 #[error("spec error: {0}")]
13 Spec(#[from] zlayer_spec::SpecError),
14
15 #[error("container error: {0}")]
17 Container(#[from] ContainerError),
18
19 #[error("network error: {0}")]
21 Network(#[from] NetworkError),
22
23 #[error("runtime error: {0}")]
25 Runtime(#[from] RuntimeError),
26
27 #[error("config error: {0}")]
29 Config(#[from] ConfigError),
30
31 #[error("registry error: {0}")]
33 Registry(#[from] RegistryError),
34
35 #[error("IO error at {path}: {source}")]
37 Io {
38 path: PathBuf,
39 #[source]
40 source: std::io::Error,
41 },
42}
43
44#[derive(Debug, Error)]
46pub enum ContainerError {
47 #[error("failed to pull image {image}: {reason}")]
49 PullFailed { image: String, reason: String },
50
51 #[error("failed to create container: {0}")]
53 CreateFailed(String),
54
55 #[error("failed to start container {id}: {reason}")]
57 StartFailed { id: String, reason: String },
58
59 #[error("container {id} exited with code {code}")]
61 Exited { id: String, code: i32 },
62
63 #[error("container {id} not found")]
65 NotFound { id: String },
66
67 #[error("health check failed for {id}: {reason}")]
69 HealthCheckFailed { id: String, reason: String },
70
71 #[error("init action {action} failed for {id}: {reason}")]
73 InitActionFailed {
74 id: String,
75 action: String,
76 reason: String,
77 },
78}
79
80#[derive(Debug, Error)]
82pub enum NetworkError {
83 #[error("failed to create overlay interface {name}: {reason}")]
85 OverlayCreateFailed { name: String, reason: String },
86
87 #[error("failed to configure overlay peer: {0}")]
89 OverlayPeerFailed(String),
90
91 #[error("DNS resolution failed for {name}: {reason}")]
93 DnsFailed { name: String, reason: String },
94
95 #[error("connection timeout to {address}")]
97 ConnectionTimeout { address: String },
98
99 #[error("failed to bind port {port}: {reason}")]
101 BindFailed { port: u16, reason: String },
102}
103
104#[derive(Debug, Error)]
106pub enum RuntimeError {
107 #[error("failed to join deployment {name}: {reason}")]
109 JoinFailed { name: String, reason: String },
110
111 #[error("scheduler error: {0}")]
113 Scheduler(String),
114
115 #[error("service discovery error: {0}")]
117 ServiceDiscovery(String),
118
119 #[error("autoscaling error for {service}: {reason}")]
121 AutoscalingFailed { service: String, reason: String },
122
123 #[error("leadership lost for deployment {name}")]
125 LeadershipLost { name: String },
126}
127
128#[derive(Debug, Error)]
130pub enum ConfigError {
131 #[error("missing required configuration: {0}")]
133 Missing(String),
134
135 #[error("invalid configuration for {key}: {reason}")]
137 Invalid { key: String, reason: String },
138
139 #[error("failed to load config from {path}: {reason}")]
141 LoadFailed { path: PathBuf, reason: String },
142
143 #[error("{0}")]
145 Other(String),
146}
147
148impl ConfigError {
149 pub fn other(msg: impl Into<String>) -> ZLayerError {
151 ZLayerError::Config(ConfigError::Other(msg.into()))
152 }
153}
154
155#[derive(Debug, Error)]
157pub enum RegistryError {
158 #[error("failed to pull manifest for {image}: {reason}")]
160 ManifestFailed { image: String, reason: String },
161
162 #[error("failed to pull blob {digest}: {reason}")]
164 BlobFailed { digest: String, reason: String },
165
166 #[error("authentication failed for registry {registry}")]
168 AuthFailed { registry: String },
169
170 #[error("image {image} not found")]
172 NotFound { image: String },
173}
174
175pub type Result<T, E = ZLayerError> = std::result::Result<T, E>;
177
178pub use ZLayerError as Error;
180
181impl Error {
182 pub fn config(msg: impl Into<String>) -> Self {
184 ZLayerError::Config(ConfigError::Other(msg.into()))
185 }
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191
192 #[test]
193 fn test_error_display() {
194 let err = ContainerError::NotFound {
195 id: "test-id".to_string(),
196 };
197 assert!(err.to_string().contains("test-id"));
198 }
199}