github.com/vmware/govmomi@v0.51.0/vim25/soap/error.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package soap 6 7 import ( 8 "crypto/x509" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "reflect" 13 "strings" 14 15 "github.com/vmware/govmomi/vim25/types" 16 ) 17 18 type soapFaultError struct { 19 fault *Fault 20 } 21 22 func (s soapFaultError) Error() string { 23 msg := s.fault.String 24 25 if msg == "" { 26 if s.fault.Detail.Fault == nil { 27 msg = "unknown fault" 28 } else { 29 msg = reflect.TypeOf(s.fault.Detail.Fault).Name() 30 } 31 } 32 33 return fmt.Sprintf("%s: %s", s.fault.Code, msg) 34 } 35 36 func (s soapFaultError) MarshalJSON() ([]byte, error) { 37 out := struct { 38 Fault *Fault 39 }{ 40 Fault: s.fault, 41 } 42 return json.Marshal(out) 43 } 44 45 func (s soapFaultError) Fault() types.BaseMethodFault { 46 if s.fault != nil { 47 fault := s.fault.Detail.Fault 48 if fault == nil { 49 return nil 50 } 51 if f, ok := fault.(types.BaseMethodFault); ok { 52 return f 53 } 54 if val := reflect.ValueOf(fault); val.Kind() != reflect.Pointer { 55 ptrVal := reflect.New(val.Type()) 56 ptrVal.Elem().Set(val) 57 if f, ok := ptrVal.Interface().(types.BaseMethodFault); ok { 58 return f 59 } 60 } 61 } 62 return nil 63 } 64 65 type vimFaultError struct { 66 fault types.BaseMethodFault 67 } 68 69 func (v vimFaultError) Error() string { 70 typ := reflect.TypeOf(v.fault) 71 for typ.Kind() == reflect.Ptr { 72 typ = typ.Elem() 73 } 74 75 return typ.Name() 76 } 77 78 func (v vimFaultError) Fault() types.BaseMethodFault { 79 return v.fault 80 } 81 82 func WrapSoapFault(f *Fault) error { 83 return soapFaultError{f} 84 } 85 86 func IsSoapFault(err error) bool { 87 _, ok := err.(soapFaultError) 88 return ok 89 } 90 91 func ToSoapFault(err error) *Fault { 92 return err.(soapFaultError).fault 93 } 94 95 func WrapVimFault(v types.BaseMethodFault) error { 96 return vimFaultError{v} 97 } 98 99 func IsVimFault(err error) bool { 100 _, ok := err.(vimFaultError) 101 return ok 102 } 103 104 func ToVimFault(err error) types.BaseMethodFault { 105 return err.(vimFaultError).fault 106 } 107 108 func IsCertificateUntrusted(err error) bool { 109 // golang 1.20 introduce a new type to wrap 509 errors. So instead of 110 // casting the type, now we check the error chain contains the 111 // x509 error or not. 112 if errors.As(err, &x509.UnknownAuthorityError{}) { 113 return true 114 } 115 116 if errors.As(err, &x509.HostnameError{}) { 117 return true 118 } 119 120 // The err variable may not be a special type of x509 or HTTP 121 // error that can be validated by a type assertion. The err variable is 122 // in fact be an *errors.errorString. 123 124 msgs := []string{ 125 "certificate is not trusted", 126 "certificate signed by unknown authority", 127 } 128 129 for _, msg := range msgs { 130 if strings.HasSuffix(err.Error(), msg) { 131 return true 132 } 133 } 134 135 return false 136 }