-
Notifications
You must be signed in to change notification settings - Fork 2.9k
/
azclierror.py
265 lines (190 loc) · 8.35 KB
/
azclierror.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
import sys
import azure.cli.core.telemetry as telemetry
from knack.util import CLIError
from knack.log import get_logger
logger = get_logger(__name__)
# pylint: disable=unnecessary-pass
# Error types in AzureCLI are from different sources, and there are many general error types like CLIError, AzureError.
# Besides, many error types with different names are actually showing the same kind of error.
# For example, CloudError, CLIError and ValidationError all could be a resource-not-found error.
# Therefore, here we define the new error classes to map and categorize all of the error types from different sources.
# region: Base Layer
# Base class for all the AzureCLI defined error classes.
class AzCLIError(CLIError):
""" Base class for all the AzureCLI defined error classes.
DO NOT raise this error class in your codes. """
def __init__(self, error_msg, recommendation=None):
# error message
self.error_msg = error_msg
# manual recommendations provided based on developers' knowledge
self.recommendations = []
self.set_recommendation(recommendation)
# AI recommendations provided by Aladdin service, with tuple form: (recommendation, description)
self.aladdin_recommendations = []
# exception trace for the error
self.exception_trace = None
super().__init__(error_msg)
def set_recommendation(self, recommendation):
"""" Set manual recommendations for the error.
Command module or extension authors could call this method to provide recommendations,
the recommendations will be printed after the error message, one recommendation per line
"""
if isinstance(recommendation, str):
self.recommendations.append(recommendation)
elif isinstance(recommendation, list):
self.recommendations.extend(recommendation)
def set_aladdin_recommendation(self, recommendations):
""" Set aladdin recommendations for the error.
One item should be a tuple with the form: (recommendation, description)
"""
self.aladdin_recommendations.extend(recommendations)
def set_exception_trace(self, exception_trace):
self.exception_trace = exception_trace
def print_error(self):
from azure.cli.core.azlogging import CommandLoggerContext
from azure.cli.core.style import print_styled_text
with CommandLoggerContext(logger):
# print error message
logger.error(self.error_msg)
# print exception trace if there is
if self.exception_trace:
logger.exception(self.exception_trace)
# print recommendations to action
if self.recommendations:
for recommendation in self.recommendations:
print(recommendation, file=sys.stderr)
if self.aladdin_recommendations:
print('\nTRY THIS:', file=sys.stderr)
for recommendation, description in self.aladdin_recommendations:
print_styled_text(recommendation, file=sys.stderr)
print_styled_text(description, file=sys.stderr)
def send_telemetry(self):
telemetry.set_error_type(self.__class__.__name__)
# endregion
# region: Second Layer
# Main categories of the AzureCLI error types, used for Telemetry analysis
class UserFault(AzCLIError):
""" Users should be responsible for the errors.
DO NOT raise this error class in your codes. """
def send_telemetry(self):
super().send_telemetry()
telemetry.set_user_fault(self.error_msg)
class ServiceError(AzCLIError):
""" Azure Services should be responsible for the errors.
DO NOT raise this error class in your codes. """
def send_telemetry(self):
super().send_telemetry()
telemetry.set_failure(self.error_msg)
class ClientError(AzCLIError):
""" AzureCLI should be responsible for the errors.
DO NOT raise this error class in your codes. """
def send_telemetry(self):
super().send_telemetry()
telemetry.set_failure(self.error_msg)
if self.exception_trace:
telemetry.set_exception(self.exception_trace, '')
class UnknownError(AzCLIError):
""" Unclear errors, could not know who should be responsible for the errors.
DO NOT raise this error class in your codes. """
def send_telemetry(self):
super().send_telemetry()
telemetry.set_failure(self.error_msg)
# endregion
# region: Third Layer
# Specific categories of the AzureCLI error types
# Raise the error classes here in your codes. Avoid using fallback error classes unless you can not find a proper one.
# Command related error types
class CommandNotFoundError(UserFault):
""" Command is misspelled or not recognized by AzureCLI. """
pass
# Argument related error types
class UnrecognizedArgumentError(UserFault):
""" Argument is misspelled or not recognized by AzureCLI. """
pass
class RequiredArgumentMissingError(UserFault):
""" Required argument is not specified. """
pass
class MutuallyExclusiveArgumentError(UserFault):
""" Arguments can not be specified together. """
pass
class InvalidArgumentValueError(UserFault):
""" Argument value is not valid. """
pass
class ArgumentUsageError(UserFault):
""" Fallback of the argument usage related errors.
Avoid using this class unless the error can not be classified
into the Argument related specific error types. """
pass
# Response related error types
class BadRequestError(UserFault):
""" Bad request from client: 400 error """
pass
class UnauthorizedError(UserFault):
""" Unauthorized request: 401 error """
pass
class ForbiddenError(UserFault):
""" Service refuse to response: 403 error """
pass
class ResourceNotFoundError(UserFault):
""" Can not find Azure resources: 404 error """
pass
class AzureInternalError(ServiceError):
""" Azure service internal error: 5xx error """
pass
class AzureResponseError(UserFault):
""" Fallback of the response related errors.
Avoid using this class unless the error can not be classified
into the Response related specific error types. """
pass
# Request related error types
class AzureConnectionError(UserFault):
""" Connection issues like connection timeout, aborted or broken. """
pass
class ClientRequestError(UserFault):
""" Fallback of the request related errors. Error occurs while attempting
to make a request to the service. No request is sent.
Avoid using this class unless the error can not be classified
into the Request related specific errors types. """
pass
# File operation related error types
class FileOperationError(UserFault):
""" For file or directory operation related errors. """
pass
# Keyboard interrupt error type
class ManualInterrupt(UserFault):
""" Keyboard interrupt. """
pass
# ARM template related error types
class InvalidTemplateError(UserFault):
""" ARM template validation fails. It could be caused by incorrect template files or parameters """
pass
class DeploymentError(UserFault):
""" ARM template deployment fails. Template file is valid, and error occurs in deployment. """
pass
# Validation related error types
class ValidationError(UserFault):
""" Fallback of the errors in validation functions.
Avoid using this class unless the error can not be classified into
the Argument, Request and Response related specific error types. """
pass
class UnclassifiedUserFault(UserFault):
""" Fallback of the UserFault related error types.
Avoid using this class unless the error can not be classified into
the UserFault related specific error types.
"""
pass
# CLI internal error type
class CLIInternalError(ClientError):
""" AzureCLI internal error """
pass
# Client error for az next
class RecommendationError(ClientError):
""" The client error raised by `az next`. It is needed in `az next` to skip error records. """
pass
class AuthenticationError(ServiceError):
""" Raised when AAD authentication fails. """
# endregion