Kubernetes的error设计

463 阅读1分钟

概述

Kubernetes的error是struct error路线,只不过外面包了一个interface StatusError,然后还依赖了1.13的errors.As 特性,把error断言为StatusError。

细节

StatusError

代码位于 staging/src/k8s.io/apimachinery/pkg/api/errors

type APIStatus interface {
	Status() metav1.Status
}

type StatusError struct {
	ErrStatus metav1.Status
}

func IsNotFound(err error) bool {
	reason, code := reasonAndCodeForError(err)
	if reason == metav1.StatusReasonNotFound {
		return true
	}
	if _, ok := knownReasons[reason]; !ok && code == http.StatusNotFound {
		return true
	}
	return false
}

func reasonAndCodeForError(err error) (metav1.StatusReason, int32) {
	if status := APIStatus(nil); errors.As(err, &status) {
		return status.Status().Reason, status.Status().Code
	}
	return metav1.StatusReasonUnknown, 0
}

func NewNotFound(qualifiedResource schema.GroupResource, name string) *StatusError {
	return &StatusError{metav1.Status{
		Status: metav1.StatusFailure,
		Code:   http.StatusNotFound,
		Reason: metav1.StatusReasonNotFound,
		Details: &metav1.StatusDetails{
			Group: qualifiedResource.Group,
			Kind:  qualifiedResource.Resource,
			Name:  name,
		},
		Message: fmt.Sprintf("%s %q not found", qualifiedResource.String(), name),
	}}
}

可见,Kubernetes的error是struct error路线,只不过外面包了一个interface StatusError,然后还依赖了1.13的errors.As 特性,把error断言为StatusError。

metav1.Status 的这几个字段很重要:

  • Code:参考http状态码,判断error类型的2级依据
  • Reason:判断error类型的1级依据
  • Message:error实际返回的错误信息

AggregateError

有的时候,我们需要一个error数组,而不是单个error,errors包就提供了这种error。

type Aggregate interface {
	error
	Errors() []error
	Is(error) bool
}

func NewAggregate(errlist []error) Aggregate {
// ...
}

它具有message去重能力,error()的返回是所有error的message。还有errors.Is的封装,除此之外,不提供更多方法了。