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  }