Introduce ChainRouterError error type and wrap only these errors with ObjectAccessDenied status #1563

Merged
fyrchik merged 3 commits from aarifullin/frostfs-node:fix/ape_logicalerr into master 2024-12-17 08:24:32 +00:00
Showing only changes of commit 1a091ea7bb - Show all commits

View file

@ -1,10 +1,19 @@
package ape package ape
import ( import (
"errors"
checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
) )
func toStatusErr(err error) error { func toStatusErr(err error) error {
var chRouterErr *checkercore.ChainRouterError
if !errors.As(err, &chRouterErr) {
errServerInternal := &apistatus.ServerInternal{}
fyrchik marked this conversation as resolved Outdated

Where do we do wrapping to internal status (if we have any)?
I am wondering whether these changes may break client code (see PrmInit.ResolveFrostFSFailures() in SDK), because we will get an error instead of status.

Where do we do wrapping to internal status (if we have any)? I am wondering whether these changes may break client code (see `PrmInit.ResolveFrostFSFailures()` in SDK), because we will get an error instead of status.

We don't do that for all errors, but they are implicitly (from the point of this middleware) wrapped to internalServerError anyway. Aren't they?

func setStatusV2(resp ResponseMessage, err error) {
	// unwrap error
	for e := errors.Unwrap(err); e != nil; e = errors.Unwrap(err) {
		err = e
	}

	session.SetStatus(resp, apistatus.ToStatusV2(apistatus.ErrToStatus(err)))
}
func ToStatusV2(st Status) *status.Status {
	if v, ok := st.(StatusV2); ok {
		return v.ToStatusV2()
	}

	if IsSuccessful(st) {
		return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess)
	}

	internalErrorStatus := newStatusV2WithLocalCode(status.Internal, status.GlobalizeCommonFail)
	internalErrorStatus.SetMessage(st.(error).Error()) // type cast never panics because IsSuccessful() checks cast

	return internalErrorStatus
}

Although that's not true for tree service

We don't do that for all errors, but they are implicitly (from the point of this middleware) wrapped to `internalServerError` anyway. Aren't they? ```go func setStatusV2(resp ResponseMessage, err error) { // unwrap error for e := errors.Unwrap(err); e != nil; e = errors.Unwrap(err) { err = e } session.SetStatus(resp, apistatus.ToStatusV2(apistatus.ErrToStatus(err))) } ``` ```go func ToStatusV2(st Status) *status.Status { if v, ok := st.(StatusV2); ok { return v.ToStatusV2() } if IsSuccessful(st) { return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess) } internalErrorStatus := newStatusV2WithLocalCode(status.Internal, status.GlobalizeCommonFail) internalErrorStatus.SetMessage(st.(error).Error()) // type cast never panics because IsSuccessful() checks cast return internalErrorStatus } ``` Although that's not true for `tree` service

For now non-chainRouterError errors are explicitly wrapped with ServerInternal status for the all goodness sake

For now non-`chainRouterError` errors are explicitly wrapped with ServerInternal status for the all goodness sake
apistatus.WriteInternalServerErr(errServerInternal, err)
return errServerInternal
}
errAccessDenied := &apistatus.ObjectAccessDenied{} errAccessDenied := &apistatus.ObjectAccessDenied{}
errAccessDenied.WriteReason("ape denied request: " + err.Error()) errAccessDenied.WriteReason("ape denied request: " + err.Error())
return errAccessDenied return errAccessDenied