go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/explorer/error_status.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package explorer 5 6 import ( 7 "go.mondoo.com/ranger-rpc/codes" 8 "go.mondoo.com/ranger-rpc/status" 9 "google.golang.org/genproto/googleapis/rpc/errdetails" 10 spb "google.golang.org/genproto/googleapis/rpc/status" 11 ) 12 13 // cnquery codes start at 100 to avoid conflicts with GRPC and Ranger RPC codes 14 // see https://github.com/mondoohq/ranger-rpc/blob/main/codes/codes.go 15 type ErrorStatusCode uint32 16 17 const ( 18 Unknown ErrorStatusCode = iota + 100 19 // NotApplicable is returned when a query or asset is not applicable to the current scan 20 NotApplicable 21 // NoQueries is returned when no queries are found in the bundle for the asset 22 NoQueries 23 ) 24 25 func NewErrorStatusCodeFromString(s string) ErrorStatusCode { 26 switch s { 27 case "NotApplicable": 28 return NotApplicable 29 case "NoQueries": 30 return NoQueries 31 } 32 return Unknown 33 } 34 35 func (e ErrorStatusCode) String() string { 36 switch e { 37 case NotApplicable: 38 return "NotApplicable" 39 case NoQueries: 40 return "NoQueries" 41 default: 42 return "Unknown" 43 } 44 } 45 46 // cnquery codes start at 100 to avoid conflicts with GRPC and Ranger RPC codes 47 type ErrorCategory uint32 48 49 const ( 50 ErrorCategoryError ErrorCategory = iota 51 ErrorCategoryWarning 52 ErrorCategoryInformational 53 ) 54 55 func (e ErrorCategory) String() string { 56 switch e { 57 case ErrorCategoryInformational: 58 return "info" 59 case ErrorCategoryWarning: 60 return "warning" 61 case ErrorCategoryError: 62 return "error" 63 default: 64 return "error" 65 } 66 } 67 68 func (e ErrorStatusCode) Category() ErrorCategory { 69 switch e { 70 case NotApplicable: 71 return ErrorCategoryInformational 72 case NoQueries: 73 return ErrorCategoryWarning 74 default: 75 return ErrorCategoryError 76 } 77 } 78 79 func NewErrorStatus(err error) *ErrorStatus { 80 s, ok := status.FromError(err) 81 if !ok { 82 // not status error - just add it as a generic error 83 return &ErrorStatus{ 84 Code: int32(codes.Unknown), 85 Message: err.Error(), 86 } 87 } 88 89 // if it's a status error, add it as a status error with details if possible 90 p := s.Proto() 91 if p != nil { 92 return &ErrorStatus{ 93 Code: p.GetCode(), 94 Message: p.GetMessage(), 95 Details: p.Details, 96 } 97 } 98 return &ErrorStatus{ 99 Code: int32(s.Code()), 100 Message: s.Message(), 101 } 102 } 103 104 func (e *ErrorStatus) StatusProto() *spb.Status { 105 return &spb.Status{ 106 Code: e.Code, 107 Message: e.Message, 108 Details: e.Details, 109 } 110 } 111 112 func (e *ErrorStatus) ErrorCode() ErrorStatusCode { 113 s := status.FromProto(e.StatusProto()) 114 for _, detail := range s.Details() { 115 switch v := detail.(type) { 116 case *errdetails.ErrorInfo: 117 code, ok := v.Metadata["errorCode"] 118 if ok { 119 return NewErrorStatusCodeFromString(code) 120 } 121 } 122 } 123 124 return Unknown 125 }