55
66from typing import Any , Optional
77
8- from orb .domain .base .exceptions import InfrastructureError
8+ from orb .providers .base .exceptions import (
9+ ProviderAuthError ,
10+ ProviderConfigError ,
11+ ProviderError ,
12+ ProviderPermanentError ,
13+ ProviderQuotaError ,
14+ ProviderTransientError ,
15+ )
916
1017
11- class AzureError (InfrastructureError ):
18+ class AzureError (ProviderError ):
1219 """Base class for Azure-related errors."""
1320
1421 def __init__ (
1522 self ,
1623 message : str ,
1724 details : Optional [dict [str , Any ]] = None ,
1825 error_code : Optional [str ] = None ,
26+ * ,
27+ provider_name : Optional [str ] = None ,
28+ underlying_exception : Optional [BaseException ] = None ,
29+ is_retryable : Optional [bool ] = None ,
1930 ) -> None :
20- super ().__init__ (message , error_code or self .__class__ .__name__ , details )
31+ super ().__init__ (
32+ message ,
33+ provider_type = "azure" ,
34+ provider_name = provider_name ,
35+ underlying_exception = underlying_exception ,
36+ details = details ,
37+ is_retryable = is_retryable ,
38+ )
2139 self .error_code = error_code or self .__class__ .__name__
2240
2341 def to_dict (self ) -> dict [str , Any ]:
@@ -27,13 +45,20 @@ def to_dict(self) -> dict[str, Any]:
2745 result ["error_code" ] = self .error_code
2846 return result
2947
48+ def safe_to_dict (self ) -> dict [str , Any ]:
49+ """Serialize the exception without exposing its underlying exception."""
50+ result = super ().safe_to_dict ()
51+ if self .error_code and self .error_code != self .__class__ .__name__ :
52+ result ["error_code" ] = self .error_code
53+ return result
54+
3055
3156# ---------------------------------------------------------------------------
3257# Validation
3358# ---------------------------------------------------------------------------
3459
3560
36- class AzureValidationError (AzureError ):
61+ class AzureValidationError (AzureError , ProviderPermanentError ):
3762 """Raised when Azure resource validation fails."""
3863
3964
@@ -66,7 +91,7 @@ def __init__(self, message: str, image_ref: str, details: Optional[dict[str, Any
6691# ---------------------------------------------------------------------------
6792
6893
69- class AzureEntityNotFoundError (AzureError ):
94+ class AzureEntityNotFoundError (AzureError , ProviderPermanentError ):
7095 """Raised when an Azure resource is not found."""
7196
7297
@@ -91,7 +116,7 @@ def __init__(self, message: str, vmss_name: str, details: Optional[dict[str, Any
91116# ---------------------------------------------------------------------------
92117
93118
94- class QuotaExceededError (AzureError ):
119+ class QuotaExceededError (AzureError , ProviderQuotaError ):
95120 """Raised when Azure service quotas would be exceeded."""
96121
97122
@@ -128,11 +153,11 @@ def __init__(
128153# ---------------------------------------------------------------------------
129154
130155
131- class ResourceInUseError (AzureError ):
156+ class ResourceInUseError (AzureError , ProviderTransientError ):
132157 """Raised when an Azure resource is already in use."""
133158
134159
135- class ResourceStateError (AzureError ):
160+ class ResourceStateError (AzureError , ProviderTransientError ):
136161 """Raised when a resource is in an invalid state for the operation."""
137162
138163 def __init__ (
@@ -162,11 +187,11 @@ def __init__(
162187# ---------------------------------------------------------------------------
163188
164189
165- class AuthenticationError (AzureError ):
190+ class AuthenticationError (AzureError , ProviderAuthError ):
166191 """Raised when Azure authentication fails."""
167192
168193
169- class AuthorizationError (AzureError ):
194+ class AuthorizationError (AzureError , ProviderAuthError ):
170195 """Raised when there are insufficient permissions."""
171196
172197
@@ -193,11 +218,11 @@ def __init__(
193218# ---------------------------------------------------------------------------
194219
195220
196- class RateLimitError (AzureError ):
221+ class RateLimitError (AzureError , ProviderQuotaError ):
197222 """Raised when Azure API rate limits are exceeded."""
198223
199224
200- class NetworkError (AzureError ):
225+ class NetworkError (AzureError , ProviderTransientError ):
201226 """Raised when there are network-related issues."""
202227
203228
@@ -206,11 +231,11 @@ class NetworkError(AzureError):
206231# ---------------------------------------------------------------------------
207232
208233
209- class AzureInfrastructureError (AzureError ):
234+ class AzureInfrastructureError (AzureError , ProviderTransientError ):
210235 """Raised for general Azure infrastructure errors."""
211236
212237
213- class AzureConfigurationError (AzureError ):
238+ class AzureConfigurationError (AzureError , ProviderConfigError ):
214239 """Raised when Azure configuration is invalid."""
215240
216241
@@ -219,7 +244,7 @@ class AzureConfigurationError(AzureError):
219244# ---------------------------------------------------------------------------
220245
221246
222- class LaunchError (AzureError ):
247+ class LaunchError (AzureError , ProviderTransientError ):
223248 """Instance / VMSS launch failed."""
224249
225250 def __init__ (
@@ -265,7 +290,7 @@ def __init__(
265290 self .vmss_name = vmss_name
266291
267292
268- class TerminationError (AzureError ):
293+ class TerminationError (AzureError , ProviderTransientError ):
269294 """Instance termination failed."""
270295
271296 def __init__ (
@@ -281,7 +306,7 @@ def __init__(
281306 self .resource_ids = resource_ids
282307
283308
284- class ResourceCleanupError (AzureError ):
309+ class ResourceCleanupError (AzureError , ProviderTransientError ):
285310 """Failed to clean up Azure resources."""
286311
287312 def __init__ (
@@ -303,7 +328,7 @@ def __init__(
303328 self .resource_type = resource_type
304329
305330
306- class TaggingError (AzureError ):
331+ class TaggingError (AzureError , ProviderTransientError ):
307332 """Failed to tag Azure resources."""
308333
309334 def __init__ (
@@ -330,7 +355,7 @@ class CycleCloudError(AzureError):
330355 """Base class for CycleCloud-related errors."""
331356
332357
333- class CycleCloudConnectionError (CycleCloudError ):
358+ class CycleCloudConnectionError (CycleCloudError , ProviderTransientError ):
334359 """Failed to connect to the CycleCloud REST API."""
335360
336361 def __init__ (
@@ -346,7 +371,7 @@ def __init__(
346371 self .url = url
347372
348373
349- class CycleCloudClusterNotFoundError (CycleCloudError ):
374+ class CycleCloudClusterNotFoundError (CycleCloudError , ProviderPermanentError ):
350375 """The specified CycleCloud cluster was not found."""
351376
352377 def __init__ (
@@ -362,7 +387,7 @@ def __init__(
362387 self .cluster_name = cluster_name
363388
364389
365- class CycleCloudNodeError (CycleCloudError ):
390+ class CycleCloudNodeError (CycleCloudError , ProviderTransientError ):
366391 """Failed to add or manage CycleCloud nodes."""
367392
368393 def __init__ (
0 commit comments