github.com/vmware/govmomi@v0.37.1/vim25/soap/error.go (about) 1 /* 2 Copyright (c) 2014 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package soap 18 19 import ( 20 "crypto/x509" 21 "encoding/json" 22 "errors" 23 "fmt" 24 "reflect" 25 "strings" 26 27 "github.com/vmware/govmomi/vim25/types" 28 ) 29 30 type regularError struct { 31 err error 32 } 33 34 func (r regularError) Error() string { 35 return r.err.Error() 36 } 37 38 type soapFaultError struct { 39 fault *Fault 40 } 41 42 func (s soapFaultError) Error() string { 43 msg := s.fault.String 44 45 if msg == "" { 46 if s.fault.Detail.Fault == nil { 47 msg = "unknown fault" 48 } else { 49 msg = reflect.TypeOf(s.fault.Detail.Fault).Name() 50 } 51 } 52 53 return fmt.Sprintf("%s: %s", s.fault.Code, msg) 54 } 55 56 func (s soapFaultError) MarshalJSON() ([]byte, error) { 57 out := struct { 58 Fault *Fault 59 }{ 60 Fault: s.fault, 61 } 62 return json.Marshal(out) 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 Wrap(err error) error { 83 switch err.(type) { 84 case regularError: 85 return err 86 case soapFaultError: 87 return err 88 case vimFaultError: 89 return err 90 } 91 92 return WrapRegularError(err) 93 } 94 95 func WrapRegularError(err error) error { 96 return regularError{err} 97 } 98 99 func IsRegularError(err error) bool { 100 _, ok := err.(regularError) 101 return ok 102 } 103 104 func ToRegularError(err error) error { 105 return err.(regularError).err 106 } 107 108 func WrapSoapFault(f *Fault) error { 109 return soapFaultError{f} 110 } 111 112 func IsSoapFault(err error) bool { 113 _, ok := err.(soapFaultError) 114 return ok 115 } 116 117 func ToSoapFault(err error) *Fault { 118 return err.(soapFaultError).fault 119 } 120 121 func WrapVimFault(v types.BaseMethodFault) error { 122 return vimFaultError{v} 123 } 124 125 func IsVimFault(err error) bool { 126 _, ok := err.(vimFaultError) 127 return ok 128 } 129 130 func ToVimFault(err error) types.BaseMethodFault { 131 return err.(vimFaultError).fault 132 } 133 134 func IsCertificateUntrusted(err error) bool { 135 // golang 1.20 introduce a new type to wrap 509 errors. So instead of 136 // casting the type, now we check the error chain contains the 137 // x509 error or not. 138 x509UnknownAuthorityErr := &x509.UnknownAuthorityError{} 139 ok := errors.As(err, x509UnknownAuthorityErr) 140 if ok { 141 return true 142 } 143 144 x509HostNameErr := &x509.HostnameError{} 145 ok = errors.As(err, x509HostNameErr) 146 if ok { 147 return true 148 } 149 150 // The err variable may not be a special type of x509 or HTTP 151 // error that can be validated by a type assertion. The err variable is 152 // in fact be an *errors.errorString. 153 154 msgs := []string{ 155 "certificate is not trusted", 156 "certificate signed by unknown authority", 157 } 158 159 for _, msg := range msgs { 160 if strings.HasSuffix(err.Error(), msg) { 161 return true 162 } 163 } 164 165 return false 166 }