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  }