Skip to content

Commit

Permalink
Fix record not found unmarshall. Fixes #1983
Browse files Browse the repository at this point in the history
  • Loading branch information
plorenz committed Apr 25, 2024
1 parent f5181e0 commit 67a6370
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 10 deletions.
8 changes: 6 additions & 2 deletions controller/handler_peer_ctrl/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ package handler_peer_ctrl

import (
"encoding/json"
"fmt"
"github.com/hashicorp/raft"
"github.com/openziti/channel/v2"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/ziti/common/pb/cmd_pb"
"github.com/openziti/ziti/controller/models"
"github.com/openziti/ziti/controller/peermsg"
"github.com/openziti/ziti/common/pb/cmd_pb"
"github.com/openziti/foundation/v2/errorz"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -52,6 +53,9 @@ func sendApiErrorResponse(m *channel.Message, ch channel.Channel, err *errorz.Ap
encodingMap["message"] = err.Message
encodingMap["status"] = err.Status
encodingMap["cause"] = err.Cause
if err.Cause != nil {
encodingMap["causeType"] = fmt.Sprintf("%T", err.Cause)
}

buf, encodeErr := json.Marshal(encodingMap)
if encodeErr != nil {
Expand Down
63 changes: 55 additions & 8 deletions controller/raft/raft.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"encoding/json"
"fmt"
"github.com/hashicorp/go-hclog"
"github.com/mitchellh/mapstructure"
"github.com/openziti/foundation/v2/concurrenz"
"github.com/openziti/foundation/v2/rate"
"github.com/openziti/foundation/v2/versions"
Expand Down Expand Up @@ -209,7 +210,9 @@ func NewController(env Env, migrationMgr MigrationManager) *Controller {
migrationMgr: migrationMgr,
clusterEvents: make(chan raft.Observation, 16),
commandRateLimiter: command.NewRateLimiter(env.GetCommandRateLimiterConfig(), env.GetMetricsRegistry(), env.GetCloseNotify()),
errorMappers: map[string]func(map[string]any) error{},
}
result.initErrorMappers()
return result
}

Expand All @@ -230,6 +233,12 @@ type Controller struct {
isLeader atomic.Bool
clusterEvents chan raft.Observation
commandRateLimiter rate.RateLimiter
errorMappers map[string]func(map[string]any) error
}

func (self *Controller) initErrorMappers() {
self.errorMappers[fmt.Sprintf("%T", &boltz.RecordNotFoundError{})] = self.parseBoltzNotFoundError
self.errorMappers[fmt.Sprintf("%T", &errorz.FieldError{})] = self.parseFieldError
}

func (self *Controller) RegisterClusterEventHandler(f func(event ClusterEvent, state ClusterState)) {
Expand Down Expand Up @@ -408,14 +417,16 @@ func (self *Controller) decodeApiError(data []byte) error {
if cause, ok := m["cause"]; ok {
if strCause, ok := cause.(string); ok {
apiErr.Cause = errors.New(strCause)
} else if objCause, ok := cause.(map[string]interface{}); ok {
apiErr.Cause = self.parseFieldError(objCause)
} else if objCause, ok := cause.(map[string]any); ok {
if parser := self.getErrorParser(m); parser != nil {
pfxlog.Logger().Info("parser found for cause type")
apiErr.Cause = parser(objCause)
} else {
pfxlog.Logger().Info("no parser found for cause type")
}

if apiErr.Cause == nil {
if b, err := json.Marshal(objCause); err == nil {
apiErr.Cause = errors.New(string(b))
} else {
apiErr.Cause = errors.New(fmt.Sprintf("%+v", objCause))
}
apiErr.Cause = self.fallbackMarshallError(objCause)
}
} else {
pfxlog.Logger().Warnf("invalid api error encoding, no cause: %v", string(data))
Expand All @@ -426,7 +437,7 @@ func (self *Controller) decodeApiError(data []byte) error {
return apiErr
}

func (self *Controller) parseFieldError(m map[string]any) *errorz.FieldError {
func (self *Controller) parseFieldError(m map[string]any) error {
var fieldError *errorz.FieldError
field, ok := m["field"]
if !ok {
Expand Down Expand Up @@ -456,6 +467,42 @@ func (self *Controller) parseFieldError(m map[string]any) *errorz.FieldError {
return fieldError
}

func (self *Controller) parseBoltzNotFoundError(m map[string]any) error {
result := &boltz.RecordNotFoundError{}
err := mapstructure.Decode(m, result)
if err != nil {
multi := errorz.MultipleErrors{}
multi = append(multi, fmt.Errorf("unable to decode RecordNotFoundError (%w)", err))

Check failure on line 475 in controller/raft/raft.go

View workflow job for this annotation

GitHub Actions / lint

SA4010: this result of append is never used, except maybe in other appends (staticcheck)
multi = append(multi, self.fallbackMarshallError(m))

Check failure on line 476 in controller/raft/raft.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to multi (ineffassign)
}
return result
}

func (self *Controller) fallbackMarshallError(m map[string]any) error {
if b, err := json.Marshal(m); err == nil {
return errors.New(string(b))
}
return errors.New(fmt.Sprintf("%+v", m))
}

func (self *Controller) getErrorParser(m map[string]any) func(map[string]any) error {
causeType, ok := m["causeType"]
if !ok {
pfxlog.Logger().Info("no causetype defined for error parser")
return nil
}

causeTypeStr, ok := causeType.(string)
if !ok {
pfxlog.Logger().Info("causetype not string")
return nil
}

pfxlog.Logger().Infof("causetype %s", causeTypeStr)

return self.errorMappers[causeTypeStr]
}

// applyCommand encodes the command and passes it to ApplyEncodedCommand
func (self *Controller) applyCommand(cmd command.Command) (uint64, error) {
encoded, err := cmd.Encode()
Expand Down

0 comments on commit 67a6370

Please sign in to comment.