lmrc_docker/error/
mod.rs

1//! Error types for the docker-client library.
2
3use thiserror::Error;
4
5/// Result type alias for docker-client operations.
6pub type Result<T> = std::result::Result<T, DockerError>;
7
8/// Main error type for docker-client operations.
9#[derive(Debug, Error)]
10pub enum DockerError {
11    /// Error connecting to Docker daemon
12    #[error("Failed to connect to Docker daemon: {0}")]
13    Connection(String),
14
15    /// Container not found
16    #[error("Container not found: {0}")]
17    ContainerNotFound(String),
18
19    /// Image not found
20    #[error("Image not found: {0}")]
21    ImageNotFound(String),
22
23    /// Network not found
24    #[error("Network not found: {0}")]
25    NetworkNotFound(String),
26
27    /// Volume not found
28    #[error("Volume not found: {0}")]
29    VolumeNotFound(String),
30
31    /// Build operation failed
32    #[error("Docker build failed: {0}")]
33    BuildFailed(String),
34
35    /// Push operation failed
36    #[error("Docker push failed: {0}")]
37    PushFailed(String),
38
39    /// Pull operation failed
40    #[error("Docker pull failed: {0}")]
41    PullFailed(String),
42
43    /// Container operation failed
44    #[error("Container operation failed: {0}")]
45    ContainerOperationFailed(String),
46
47    /// Image operation failed
48    #[error("Image operation failed: {0}")]
49    ImageOperationFailed(String),
50
51    /// Invalid configuration
52    #[error("Invalid configuration: {0}")]
53    InvalidConfiguration(String),
54
55    /// Invalid image tag format
56    #[error("Invalid image tag format: {0}")]
57    InvalidImageTag(String),
58
59    /// Authentication failed
60    #[error("Authentication failed: {0}")]
61    AuthenticationFailed(String),
62
63    /// I/O error
64    #[error("I/O error: {0}")]
65    Io(#[from] std::io::Error),
66
67    /// Bollard API error
68    #[error("Docker API error: {0}")]
69    Api(#[from] bollard::errors::Error),
70
71    /// Serialization error
72    #[error("Serialization error: {0}")]
73    Serialization(#[from] serde_json::Error),
74
75    /// Generic error
76    #[error("{0}")]
77    Other(String),
78}
79
80impl From<String> for DockerError {
81    fn from(s: String) -> Self {
82        DockerError::Other(s)
83    }
84}
85
86impl From<&str> for DockerError {
87    fn from(s: &str) -> Self {
88        DockerError::Other(s.to_string())
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_error_display() {
98        let err = DockerError::ContainerNotFound("test-container".to_string());
99        assert_eq!(err.to_string(), "Container not found: test-container");
100
101        let err = DockerError::ImageNotFound("test-image:latest".to_string());
102        assert_eq!(err.to_string(), "Image not found: test-image:latest");
103
104        let err = DockerError::Connection("timeout".to_string());
105        assert_eq!(
106            err.to_string(),
107            "Failed to connect to Docker daemon: timeout"
108        );
109
110        let err = DockerError::BuildFailed("syntax error".to_string());
111        assert_eq!(err.to_string(), "Docker build failed: syntax error");
112
113        let err = DockerError::InvalidConfiguration("missing field".to_string());
114        assert_eq!(err.to_string(), "Invalid configuration: missing field");
115    }
116
117    #[test]
118    fn test_error_from_string() {
119        let err: DockerError = "test error".into();
120        assert_eq!(err.to_string(), "test error");
121
122        let err: DockerError = String::from("another error").into();
123        assert_eq!(err.to_string(), "another error");
124    }
125
126    #[test]
127    fn test_error_from_io() {
128        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
129        let err: DockerError = io_err.into();
130        assert!(err.to_string().contains("I/O error"));
131    }
132
133    #[test]
134    fn test_result_type() {
135        fn returns_error() -> Result<()> {
136            Err(DockerError::Other("test".to_string()))
137        }
138
139        let result = returns_error();
140        assert!(result.is_err());
141    }
142
143    #[test]
144    fn test_all_error_variants() {
145        let errors = vec![
146            DockerError::Connection("test".to_string()),
147            DockerError::ContainerNotFound("test".to_string()),
148            DockerError::ImageNotFound("test".to_string()),
149            DockerError::NetworkNotFound("test".to_string()),
150            DockerError::VolumeNotFound("test".to_string()),
151            DockerError::BuildFailed("test".to_string()),
152            DockerError::PushFailed("test".to_string()),
153            DockerError::PullFailed("test".to_string()),
154            DockerError::ContainerOperationFailed("test".to_string()),
155            DockerError::ImageOperationFailed("test".to_string()),
156            DockerError::InvalidConfiguration("test".to_string()),
157            DockerError::InvalidImageTag("test".to_string()),
158            DockerError::AuthenticationFailed("test".to_string()),
159            DockerError::Other("test".to_string()),
160        ];
161
162        for err in errors {
163            assert!(!err.to_string().is_empty());
164        }
165    }
166}