alibabacloudstack/errmsgs/errors.go (354 lines of code) (raw):

package errmsgs import ( "encoding/json" "errors" "reflect" "regexp" "strings" "github.com/alibabacloud-go/tea/tea" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" sls "github.com/aliyun/aliyun-log-go-sdk" "fmt" "log" "runtime" sdkerrors "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" //"github.com/aliyun/aliyun-datahub-sdk-go/datahub" "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/fc-go-sdk" "github.com/denverdino/aliyungo/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) const ( // common NotFound = "NotFound" ResourceNotfound = "ResourceNotfound" InstanceNotFound = "Instance.Notfound" VSwitchIdNotFound = "VSwitchId.Notfound" MessageInstanceNotFound = "instance is not found" Throttling = "Throttling" ServiceUnavailable = "ServiceUnavailable" // RAM Instance Not Found RamInstanceNotFound = "Forbidden.InstanceNotFound" AlibabacloudStackGoClientFailure = "AlibabacloudStackGoClientFailure" DenverdinoAlibabacloudStackgo = ErrorSource("[SDK denverdino/aliyungo ERROR]") ThrottlingUser = "Throttling.User" LogClientTimeout = "Client.Timeout exceeded while awaiting headers" AlibabacloudstackMaxComputeSdkGo = ErrorSource("[SDK aliyun-maxcompute-sdk-go ERROR]") InvalidFileSystemStatus_Ordering = "InvalidFileSystemStatus.Ordering" ) var SlbIsBusy = []string{"SystemBusy", "OperationBusy", "ServiceIsStopping", "BackendServer.configuring", "ServiceIsConfiguring"} var EcsNotFound = []string{"InvalidInstanceId.NotFound", "Forbidden.InstanceNotFound"} var DiskInvalidOperation = []string{"IncorrectDiskStatus", "IncorrectInstanceStatus", "OperationConflict", "InternalError", "InvalidOperation.Conflict", "IncorrectDiskStatus.Initializing"} var NetworkInterfaceInvalidOperations = []string{"InvalidOperation.InvalidEniState", "InvalidOperation.InvalidEcsState", "OperationConflict", "ServiceUnavailable", "InternalError"} var SnapshotInvalidOperations = []string{"OperationConflict", "ServiceUnavailable", "InternalError", "SnapshotCreatedDisk", "SnapshotCreatedImage"} var SnapshotPolicyInvalidOperations = []string{"OperationConflict", "ServiceUnavailable", "InternalError", "SnapshotCreatedDisk", "SnapshotCreatedImage"} var DiskNotSupportOnlineChangeErrors = []string{"InvalidDiskCategory.NotSupported", "InvalidRegion.NotSupport", "IncorrectInstanceStatus", "IncorrectDiskStatus", "InvalidOperation.InstanceTypeNotSupport"} var DBReadInstanceNotReadyStatus = []string{"OperationDenied.ReadDBInstanceStatus", "OperationDenied.MasterDBInstanceState", "ReadDBInstance.Mismatch"} // An Error represents a custom error for Terraform failure response type ProviderError struct { errorCode string message string } // details at: https://help.aliyun.com/document_detail/27300.html var OtsTableIsTemporarilyUnavailable = []string{"no such host", "OTSServerBusy", "OTSPartitionUnavailable", "OTSInternalServerError", "OTSTimeout", "OTSServerUnavailable", "OTSRowOperationConflict", "OTSTableNotReady", "OTSNotEnoughCapacityUnit", "Too frequent table operations."} func (e *ProviderError) Error() string { return fmt.Sprintf("[ERROR] Terraform AlibabacloudStack Provider Error: Code: %s Message: %s", e.errorCode, e.message) } func (err *ProviderError) ErrorCode() string { return err.errorCode } func (err *ProviderError) Message() string { return err.message } func GetNotFoundErrorFromString(str string) error { return &ProviderError{ errorCode: InstanceNotFound, message: str, } } func GetNotFoundVPCError(str string) error { return &ProviderError{ errorCode: VSwitchIdNotFound, message: str, } } func NotFoundError(err error) bool { if err == nil { return false } if e, ok := err.(*ComplexError); ok { if e.Err != nil && strings.HasPrefix(e.Err.Error(), ResourceNotfound) { return true } return NotFoundError(e.Cause) } if err == nil { return false } if e, ok := err.(*sdkerrors.ServerError); ok { return e.ErrorCode() == InstanceNotFound || e.ErrorCode() == RamInstanceNotFound || e.ErrorCode() == NotFound || strings.Contains(strings.ToLower(e.Message()), MessageInstanceNotFound) } if e, ok := err.(*ProviderError); ok { return e.ErrorCode() == InstanceNotFound || e.ErrorCode() == RamInstanceNotFound || e.ErrorCode() == NotFound || strings.Contains(strings.ToLower(e.Message()), MessageInstanceNotFound) } if e, ok := err.(*common.Error); ok { return e.Code == InstanceNotFound || e.Code == RamInstanceNotFound || e.Code == NotFound || strings.Contains(strings.ToLower(e.Message), MessageInstanceNotFound) } if e, ok := err.(oss.ServiceError); ok { return e.StatusCode == 404 || strings.HasPrefix(e.Code, "NoSuch") || strings.HasPrefix(e.Message, "No Row found") || strings.HasPrefix(e.Message, "ResourceNotfound") } if e, ok := err.(*tea.SDKError); ok { return *e.StatusCode == 404 || strings.HasSuffix(*e.Code, ".NotFound") } return false } func NeedRetry(err error) bool { if err == nil { return false } postRegex := regexp.MustCompile("^Post [\"]*https://.*") if postRegex.MatchString(err.Error()) { return true } throttlingRegex := regexp.MustCompile("^Throttling.*") codeRegex := regexp.MustCompile("^code: 5[\\d]{2}") if e, ok := err.(*tea.SDKError); ok { if strings.Contains(*e.Message, "code: 500, 您已开通过") { return false } if strings.Contains(*e.Message, "The current status of the resource does not support this operation, please retry again.") { return true } if *e.Code == ServiceUnavailable || *e.Code == "Rejected.Throttling" || throttlingRegex.MatchString(*e.Code) || codeRegex.MatchString(*e.Message) { return true } } if e, ok := err.(*sdkerrors.ServerError); ok { return e.ErrorCode() == ServiceUnavailable || e.ErrorCode() == "Rejected.Throttling" || throttlingRegex.MatchString(e.ErrorCode()) || codeRegex.MatchString(e.Message()) } if e, ok := err.(*common.Error); ok { return e.Code == ServiceUnavailable || e.Code == "Rejected.Throttling" || throttlingRegex.MatchString(e.Code) || codeRegex.MatchString(e.Message) } return false } func IsExpectedErrorCodes(code string, errorCodes []string) bool { if code == "" { return false } for _, v := range errorCodes { if v == code { return true } } return false } func IsExpectedErrors(err error, expectCodes []string) bool { if err == nil { return false } if e, ok := err.(*ComplexError); ok { return IsExpectedErrors(e.Cause, expectCodes) } if err == nil { return false } if e, ok := err.(*sdkerrors.ServerError); ok { for _, code := range expectCodes { if e.ErrorCode() == code || strings.Contains(e.Message(), code) { return true } } return false } if e, ok := err.(*ProviderError); ok { for _, code := range expectCodes { if e.ErrorCode() == code || strings.Contains(e.Message(), code) { return true } } return false } if e, ok := err.(*common.Error); ok { for _, code := range expectCodes { if e.Code == code || strings.Contains(e.Message, code) { return true } } return false } if e, ok := err.(*sls.Error); ok { for _, code := range expectCodes { if e.Code == code || strings.Contains(e.Message, code) || strings.Contains(e.String(), code) { return true } } return false } if e, ok := err.(oss.ServiceError); ok { for _, code := range expectCodes { if e.Code == code || strings.Contains(e.Message, code) { return true } } return false } if e, ok := err.(*fc.ServiceError); ok { for _, code := range expectCodes { if e.ErrorCode == code || strings.Contains(e.ErrorMessage, code) { return true } } return false } /*if e, ok := err.(datahub.DatahubError); ok { for _, code := range expectCodes { if e.Code == code || strings.Contains(e.Message, code) { return true } } return false }*/ for _, code := range expectCodes { if strings.Contains(err.Error(), code) { return true } } return false } func IsThrottling(err error) bool { if err == nil { return false } if e, ok := err.(*sdkerrors.ServerError); ok { if e.ErrorCode() == Throttling { return true } return false } if e, ok := err.(*common.Error); ok { if e.Code == Throttling { return true } return false } return false } func GetTimeErrorFromString(str string) error { return &ProviderError{ errorCode: "WaitForTimeout", message: str, } } func GetNotFoundMessage(product string, id string) string { return fmt.Sprintf("The specified %s %s is not found.", product, id) } func GetNotVPCMessage() string { return fmt.Sprintf("The VSwitchId is not found.") } func GetTimeoutMessage(product string, status string) string { return fmt.Sprintf("Waitting for %s %s is timeout.", product, status) } type ErrorSource string const ( AlibabacloudStackSdkGoERROR = ErrorSource("[SDK alibaba-cloud-sdk-go ERROR]") ProviderERROR = ErrorSource("[Provider ERROR]") AlibabacloudStackOssGoSdk = ErrorSource("[SDK aliyun-oss-go-sdk ERROR]") AlibabacloudStackLogGoSdkERROR = ErrorSource("[SDK aliyun-log-go-sdk ERROR]") AliyunTablestoreGoSdk = ErrorSource("[SDK aliyun-tablestore-go-sdk ERROR]") AlibabacloudStackDatahubSdkGo = ErrorSource("[SDK aliyun-datahub-sdk-go ERROR]") DenverdinoAliyungo = ErrorSource("[SDK denverdino/aliyungo ERROR]") ) // ComplexError is a format error which including origin error, extra error message, error occurred file and line // Cause: a error is a origin error that comes from SDK, some exceptions and so on // Err: a new error is built from extra message // Path: the file path of error occurred // Line: the file line of error occurred type ComplexError struct { Cause error Err error Path string Line int } func (e ComplexError) Error() string { if e.Cause == nil { e.Cause = Error("<nil cause>") } if e.Err == nil { return fmt.Sprintf("[ERROR] %s:%d:\n%s", e.Path, e.Line, e.Cause.Error()) } return fmt.Sprintf("[ERROR] %s:%d: %s:\n%s", e.Path, e.Line, e.Err.Error(), e.Cause.Error()) } func Error(msg string, args ...interface{}) error { return fmt.Errorf(msg, args...) } // Return a ComplexError which including error occurred file and path func WrapError(cause error) error { if cause == nil { return nil } _, filepath, line, ok := runtime.Caller(1) if !ok { log.Printf("[ERROR] runtime.Caller error in WrapError.") return WrapComplexError(cause, nil, "", -1) } parts := strings.Split(filepath, "/") if len(parts) > 3 { filepath = strings.Join(parts[len(parts)-3:], "/") } return WrapComplexError(cause, nil, filepath, line) } // Return a ComplexError which including extra error message, error occurred file and path func WrapErrorf(cause error, msg string, args ...interface{}) error { if cause == nil && strings.TrimSpace(msg) == "" { return nil } _, filepath, line, ok := runtime.Caller(1) if !ok { log.Printf("[ERROR] runtime.Caller error in WrapErrorf.") return WrapComplexError(cause, Error(msg), "", -1) } parts := strings.Split(filepath, "/") if len(parts) > 3 { filepath = strings.Join(parts[len(parts)-3:], "/") } // The second parameter of args is requestId, if the error message is NotFoundMsg the requestId need to be returned. if msg == NotFoundMsg && len(args) == 2 { msg += RequestIdMsg } return WrapComplexError(cause, fmt.Errorf(msg, args...), filepath, line) } func WrapComplexError(cause, err error, filepath string, fileline int) error { return &ComplexError{ Cause: cause, Err: err, Path: filepath, Line: fileline, } } func GetBaseResponseErrorMessage(err_response *responses.BaseResponse) (showMsg string) { raw_data := make(map[string]interface{}) err := json.Unmarshal(err_response.GetHttpContentBytes(), &raw_data) if err != nil { return } return GetAsapiErrorMessage(raw_data) } func GetAsapiErrorMessage(raw_data map[string]interface{}) (showMsg string) { showfields := []string{"errorTitle", "errorMessage", "errorCode", "eagleEyeTraceId", "RequestId"} for _, field := range showfields { value := raw_data[field] if value != nil { showMsg = showMsg + fmt.Sprintf("\n%s: %s", field, value) } } return showMsg } func CheckEmpty(value interface{}, schemaType schema.ValueType, keys ...string) error { zero := schemaType.Zero() empty := false if eq, ok := value.(schema.Equal); ok { empty = eq.Equal(zero) } else { empty = reflect.DeepEqual(value, zero) } if !empty { return nil } errmsg := strings.Join(keys, " or ") return errors.New(errmsg + " can not be empty at the same time") } // A default message of ComplexError's Err. It is format to Resource <resource-id> <operation> Failed!!! <error source> const IdMsg = "Resource id:%s " const DefaultErrorMsg = "Resource %s %s Failed!!! %s" const RequestV1ErrorMsg = "Resource %s %s Failed!!! %s%s" const UpdateFailedErrorMsg = "Resource %s fields: %s not update allowed!!! %s" const VPCErrorMsg = "Resource %s %s Failed!!! %s" const RequestIdMsg = "RequestId: %s" const NotFoundMsg = ResourceNotfound + "!!! %s" const WaitTimeoutMsg = "Resource %s %s Timeout In %d Seconds. Got: %s Expected: %s !!! %s" const DataDefaultErrorMsg = "Datasource %s %s Failed!!! %s" var OperationDeniedDBStatus = []string{"OperationDenied.DBStatus", "OperationDenied.DBInstanceStatus", "OperationDenied.DBClusterStatus", "InternalError", "OperationDenied.OutofUsage"} const DefaultTimeoutMsg = "Resource %s %s Timeout!!! %s" const DefaultDebugMsg = "\n*************** %s Response *************** \n%s\n%s******************************\n\n" const FailedToReachTargetStatus = "Failed to reach target status. Current status is %s." const FailedGetAttributeMsg = "Getting resource %s attribute by path %s failed!!! Body: %v." const NotFoundWithResponse = ResourceNotfound + "!!! Response: %v"