llm_shield_cloud/
error.rs1use thiserror::Error;
6
7#[derive(Error, Debug)]
9pub enum CloudError {
10 #[error("Failed to initialize cloud client: {0}")]
12 ClientInit(String),
13
14 #[error("Cloud provider '{0}' not enabled. Enable with feature flag (cloud-aws, cloud-gcp, cloud-azure)")]
15 ProviderNotEnabled(String),
16
17 #[error("Failed to fetch secret '{name}': {error}")]
19 SecretFetch {
20 name: String,
21 error: String,
22 },
23
24 #[error("Failed to create secret '{name}': {error}")]
25 SecretCreate {
26 name: String,
27 error: String,
28 },
29
30 #[error("Failed to update secret '{name}': {error}")]
31 SecretUpdate {
32 name: String,
33 error: String,
34 },
35
36 #[error("Failed to delete secret '{name}': {error}")]
37 SecretDelete {
38 name: String,
39 error: String,
40 },
41
42 #[error("Invalid secret format for '{name}': {reason}")]
43 SecretFormat {
44 name: String,
45 reason: String,
46 },
47
48 #[error("Failed to list secrets: {0}")]
49 SecretList(String),
50
51 #[error("Secret not found: '{0}'")]
52 SecretNotFound(String),
53
54 #[error("Failed to fetch object '{key}' from storage: {error}")]
56 StorageFetch {
57 key: String,
58 error: String,
59 },
60
61 #[error("Failed to read storage object '{key}': {error}")]
62 StorageRead {
63 key: String,
64 error: String,
65 },
66
67 #[error("Failed to put object '{key}' to storage: {error}")]
68 StoragePut {
69 key: String,
70 error: String,
71 },
72
73 #[error("Failed to delete object '{key}' from storage: {error}")]
74 StorageDelete {
75 key: String,
76 error: String,
77 },
78
79 #[error("Failed to list storage objects with prefix '{prefix}': {error}")]
80 StorageList {
81 prefix: String,
82 error: String,
83 },
84
85 #[error("Storage object not found: '{0}'")]
86 StorageObjectNotFound(String),
87
88 #[error("Failed to export metrics: {0}")]
90 MetricsExport(String),
91
92 #[error("Failed to write log entry: {0}")]
93 LogWrite(String),
94
95 #[error("Failed to create trace span: {0}")]
96 TraceSpanCreate(String),
97
98 #[error("Failed to export trace: {0}")]
99 TraceExport(String),
100
101 #[error("Authentication failed: {0}")]
103 AuthFailed(String),
104
105 #[error("Authorization failed: {0}")]
106 AuthorizationFailed(String),
107
108 #[error("Invalid credentials: {0}")]
109 InvalidCredentials(String),
110
111 #[error("Configuration error: {0}")]
113 ConfigError(String),
114
115 #[error("Missing required configuration: {0}")]
116 MissingConfig(String),
117
118 #[error("Invalid configuration value for '{key}': {reason}")]
119 InvalidConfig {
120 key: String,
121 reason: String,
122 },
123
124 #[error("Network error: {0}")]
126 Network(String),
127
128 #[error("Connection timeout: {0}")]
129 Timeout(String),
130
131 #[error("Serialization error: {0}")]
133 Serialization(String),
134
135 #[error("Deserialization error: {0}")]
136 Deserialization(String),
137
138 #[error("Cloud operation failed: {0}")]
140 OperationFailed(String),
141
142 #[error("Internal error: {0}")]
143 Internal(String),
144}
145
146pub type Result<T> = std::result::Result<T, CloudError>;
148
149impl CloudError {
150 pub fn secret_fetch(name: impl Into<String>, error: impl Into<String>) -> Self {
152 Self::SecretFetch {
153 name: name.into(),
154 error: error.into(),
155 }
156 }
157
158 pub fn secret_create(name: impl Into<String>, error: impl Into<String>) -> Self {
160 Self::SecretCreate {
161 name: name.into(),
162 error: error.into(),
163 }
164 }
165
166 pub fn secret_update(name: impl Into<String>, error: impl Into<String>) -> Self {
168 Self::SecretUpdate {
169 name: name.into(),
170 error: error.into(),
171 }
172 }
173
174 pub fn storage_fetch(key: impl Into<String>, error: impl Into<String>) -> Self {
176 Self::StorageFetch {
177 key: key.into(),
178 error: error.into(),
179 }
180 }
181
182 pub fn storage_put(key: impl Into<String>, error: impl Into<String>) -> Self {
184 Self::StoragePut {
185 key: key.into(),
186 error: error.into(),
187 }
188 }
189}
190
191impl From<anyhow::Error> for CloudError {
193 fn from(err: anyhow::Error) -> Self {
194 CloudError::Internal(err.to_string())
195 }
196}
197
198impl From<serde_json::Error> for CloudError {
200 fn from(err: serde_json::Error) -> Self {
201 CloudError::Serialization(err.to_string())
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208
209 #[test]
210 fn test_error_display() {
211 let err = CloudError::secret_fetch("my-secret", "connection refused");
212 assert_eq!(
213 err.to_string(),
214 "Failed to fetch secret 'my-secret': connection refused"
215 );
216 }
217
218 #[test]
219 fn test_secret_not_found() {
220 let err = CloudError::SecretNotFound("test-secret".to_string());
221 assert!(err.to_string().contains("Secret not found"));
222 }
223
224 #[test]
225 fn test_provider_not_enabled() {
226 let err = CloudError::ProviderNotEnabled("AWS".to_string());
227 assert!(err.to_string().contains("not enabled"));
228 assert!(err.to_string().contains("feature flag"));
229 }
230
231 #[test]
232 fn test_from_serde_error() {
233 let json_err = serde_json::from_str::<serde_json::Value>("{invalid}")
234 .unwrap_err();
235 let cloud_err: CloudError = json_err.into();
236 assert!(matches!(cloud_err, CloudError::Serialization(_)));
237 }
238}