Change error packages for events (#1339)

This commit is contained in:
s-christoff authored and GitHub committed 2021-06-22 16:23:27 -05:00
1 parent 054549d81e
commit d143f398c0
23 files changed
+307 -324

No files matched your search

+27 -28
View File
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/go-hclog"
)
@@ -19,10 +18,10 @@ const (
func NewEventerContext(ctx context.Context, eventer *Eventer) (context.Context, error) {
const op = "event.NewEventerContext"
if ctx == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing context")
return nil, fmt.Errorf("%s: missing context: %w", op, ErrInvalidParameter)
}
if eventer == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing eventer")
return nil, fmt.Errorf("%s: missing eventer: %w", op, ErrInvalidParameter)
}
return context.WithValue(ctx, eventerKey, eventer), nil
}
@@ -41,13 +40,13 @@ func EventerFromContext(ctx context.Context) (*Eventer, bool) {
func NewRequestInfoContext(ctx context.Context, info *RequestInfo) (context.Context, error) {
const op = "event.NewRequestInfoContext"
if ctx == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing context")
return nil, fmt.Errorf("%s: missing context: %w", op, ErrInvalidParameter)
}
if info == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing request info")
return nil, fmt.Errorf("%s: missing request info: %w", op, ErrInvalidParameter)
}
if info.Id == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing request info id")
return nil, fmt.Errorf("%s: missing request info id: %w", op, ErrInvalidParameter)
}
return context.WithValue(ctx, requestInfoKey, info), nil
}
@@ -72,34 +71,34 @@ func RequestInfoFromContext(ctx context.Context) (*RequestInfo, bool) {
func WriteObservation(ctx context.Context, caller Op, opt ...Option) error {
const op = "event.WriteObservation"
if ctx == nil {
return errors.New(errors.InvalidParameter, op, "missing context")
return fmt.Errorf("%s: missing context: %w", op, ErrInvalidParameter)
}
if caller == "" {
return errors.New(errors.InvalidParameter, op, "missing operation")
return fmt.Errorf("%s: missing operation: %w", op, ErrInvalidParameter)
}
eventer, ok := EventerFromContext(ctx)
if !ok {
eventer = SysEventer()
if eventer == nil {
return errors.New(errors.InvalidParameter, op, "missing both context and system eventer")
return fmt.Errorf("%s: missing both context and system eventer: %w", op, ErrInvalidParameter)
}
}
opts := getOpts(opt...)
if opts.withDetails == nil && opts.withHeader == nil && !opts.withFlush {
return errors.New(errors.InvalidParameter, op, "you must specify either header or details options for an event payload")
return fmt.Errorf("%s: specify either header or details options for an event payload: %w", op, ErrInvalidParameter)
}
if opts.withRequestInfo == nil {
var err error
if opt, err = addCtxOptions(ctx, opt...); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
}
e, err := newObservation(caller, opt...)
if err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
if err := eventer.writeObservation(ctx, e); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
@@ -119,7 +118,7 @@ func WriteError(ctx context.Context, caller Op, e error, opt ...Option) {
eventer = SysEventer()
if eventer == nil {
logger := hclog.New(nil)
logger.Error(fmt.Sprintf("%s: no eventer available to write error: %s", op, e))
logger.Error(fmt.Sprintf("%s: no eventer available to write error: %v", op, e))
return
}
}
@@ -127,20 +126,20 @@ func WriteError(ctx context.Context, caller Op, e error, opt ...Option) {
if opts.withRequestInfo == nil {
var err error
if opt, err = addCtxOptions(ctx, opt...); err != nil {
eventer.logger.Error(errors.Wrap(err, op).Error())
eventer.logger.Error(fmt.Sprintf("%s: unable to process context options to write error: %s", op, e))
eventer.logger.Error(fmt.Sprintf("%s: %v", op, err))
eventer.logger.Error(fmt.Sprintf("%s: unable to process context options to write error: %v", op, e))
return
}
}
ev, err := newError(caller, e, opt...)
if err != nil {
eventer.logger.Error(errors.Wrap(err, op).Error())
eventer.logger.Error(fmt.Sprintf("%s: unable to create new error to write error: %s", op, e))
eventer.logger.Error(fmt.Sprintf("%s: %v", op, err))
eventer.logger.Error(fmt.Sprintf("%s: unable to create new error to write error: %v", op, e))
return
}
if err := eventer.writeError(ctx, ev); err != nil {
eventer.logger.Error(errors.Wrap(err, op).Error())
eventer.logger.Error(fmt.Sprintf("%s: unable to write error: %s", op, e))
eventer.logger.Error(fmt.Sprintf("%s: %v", op, err))
eventer.logger.Error(fmt.Sprintf("%s: unable to write error: %v", op, e))
return
}
}
@@ -155,31 +154,31 @@ func WriteError(ctx context.Context, caller Op, e error, opt ...Option) {
func WriteAudit(ctx context.Context, caller Op, opt ...Option) error {
const op = "event.WriteAudit"
if ctx == nil {
return errors.New(errors.InvalidParameter, op, "missing context")
return fmt.Errorf("%s: missing context: %w", op, ErrInvalidParameter)
}
if caller == "" {
return errors.New(errors.InvalidParameter, op, "missing operation")
return fmt.Errorf("%s: missing operation: %w", op, ErrInvalidParameter)
}
eventer, ok := EventerFromContext(ctx)
if !ok {
eventer = SysEventer()
if eventer == nil {
return errors.New(errors.InvalidParameter, op, "missing both context and system eventer")
return fmt.Errorf("%s: missing both context and system eventer: %w", op, ErrInvalidParameter)
}
}
opts := getOpts(opt...)
if opts.withRequestInfo == nil {
var err error
if opt, err = addCtxOptions(ctx, opt...); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
}
e, err := newAudit(caller, opt...)
if err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
if err := eventer.writeAudit(ctx, e); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
@@ -197,7 +196,7 @@ func addCtxOptions(ctx context.Context, opt ...Option) ([]Option, error) {
// since there will never be another with the same id
id, err := newId(string(ObservationType))
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
retOpts = append(retOpts, WithId(id))
if !opts.withFlush {
@@ -216,7 +215,7 @@ func addCtxOptions(ctx context.Context, opt ...Option) ([]Option, error) {
// another with the same id
id, err := newId(string(ObservationType))
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
retOpts = append(retOpts, WithId(id))
if !opts.withFlush {
+47 -56
View File
@@ -10,7 +10,6 @@ import (
"time"
"github.com/golang/protobuf/ptypes/wrappers"
"github.com/hashicorp/boundary/internal/errors"
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/scopes"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
@@ -53,26 +52,26 @@ func Test_NewRequestInfoContext(t *testing.T) {
name string
ctx context.Context
requestInfo *event.RequestInfo
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-ctx",
requestInfo: testInfo,
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing context",
},
{
name: "missing-request-info",
ctx: context.Background(),
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing request info",
},
{
name: "missing-request-info-id",
ctx: context.Background(),
requestInfo: testInfoMissingId,
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing request info id",
},
{
@@ -85,10 +84,10 @@ func Test_NewRequestInfoContext(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
ctx, err := event.NewRequestInfoContext(tt.ctx, tt.requestInfo)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Errorf(err, "should have gotten an error")
assert.Nilf(ctx, "context should be nil")
assert.Truef(errors.Match(tt.wantErrMatch, err), "wanted %q and got %q", tt.wantErrMatch, err)
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -154,19 +153,19 @@ func Test_NewEventerContext(t *testing.T) {
name string
ctx context.Context
eventer *event.Eventer
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-ctx",
eventer: testEventer,
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing context",
},
{
name: "missing-eventer",
ctx: context.Background(),
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing eventer",
},
{
@@ -179,10 +178,10 @@ func Test_NewEventerContext(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
ctx, err := event.NewEventerContext(tt.ctx, tt.eventer)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Errorf(err, "should have gotten an error")
assert.Nilf(ctx, "context should be nil")
assert.Truef(errors.Match(tt.wantErrMatch, err), "wanted %q and got %q", tt.wantErrMatch, err)
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -312,7 +311,7 @@ func Test_WriteObservation(t *testing.T) {
observationSinkFileName string
setup func() error
cleanup func()
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
@@ -338,7 +337,7 @@ func Test_WriteObservation(t *testing.T) {
{
name: "missing-ctx",
observationPayload: testPayloads,
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing context",
},
{
@@ -346,7 +345,7 @@ func Test_WriteObservation(t *testing.T) {
ctx: testCtx,
noOperation: true,
observationPayload: testPayloads,
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing operation",
},
{
@@ -356,14 +355,14 @@ func Test_WriteObservation(t *testing.T) {
observationPayload: []observationPayload{
{},
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrContains: "you must specify either header or details options",
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "specify either header or details options",
},
{
name: "no-ctx-eventer-and-syseventer-not-initialized",
ctx: context.Background(),
observationPayload: testPayloads,
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing both context and system eventer",
},
{
@@ -411,8 +410,8 @@ func Test_WriteObservation(t *testing.T) {
require.Greater(len(tt.observationPayload), 0)
for _, p := range tt.observationPayload {
err := event.WriteObservation(tt.ctx, event.Op(op), event.WithHeader(p.header), event.WithDetails(p.details))
if tt.wantErrMatch != nil {
require.Errorf(err, "wanted error %q", tt.wantErrMatch)
if tt.wantErrIs != nil {
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -583,7 +582,7 @@ func Test_WriteAudit(t *testing.T) {
cleanup func()
noOperation bool
noFlush bool
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
@@ -594,7 +593,7 @@ func Test_WriteAudit(t *testing.T) {
event.WithRequest(testReq),
},
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing context",
},
{
@@ -607,7 +606,7 @@ func Test_WriteAudit(t *testing.T) {
},
},
noOperation: true,
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing operation",
},
{
@@ -619,7 +618,7 @@ func Test_WriteAudit(t *testing.T) {
event.WithRequest(testReq),
},
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: event.ErrInvalidParameter,
wantErrContains: "missing both context and system eventer",
},
{
@@ -680,8 +679,8 @@ func Test_WriteAudit(t *testing.T) {
for _, opts := range tt.auditOpts {
opts := append(opts, event.WithNow(now))
err := event.WriteAudit(tt.ctx, event.Op(op), opts...)
if tt.wantErrMatch != nil {
require.Errorf(err, "wanted error %q", tt.wantErrMatch)
if tt.wantErrIs != nil {
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -785,7 +784,10 @@ func Test_WriteError(t *testing.T) {
require.NoError(t, err)
noId.Id = ""
testError := errors.New(errors.InvalidParameter, "test", "you lookin at me?")
testError := fakeError{
Msg: "test",
Code: "code",
}
tests := []struct {
name string
@@ -801,21 +803,21 @@ func Test_WriteError(t *testing.T) {
{
name: "missing-caller",
ctx: testCtx,
e: testError,
e: &testError,
noOperation: true,
noOutput: true,
},
{
name: "no-ctx-eventer-and-syseventer-not-initialized",
ctx: context.Background(),
e: testError,
e: &testError,
errSinkFileName: c.ErrorEvents.Name(),
noOutput: true,
},
{
name: "use-syseventer",
ctx: context.Background(),
e: testError,
e: &testError,
setup: func() error {
return event.InitSysEventer(hclog.Default(), c.EventerConfig)
},
@@ -825,7 +827,7 @@ func Test_WriteError(t *testing.T) {
{
name: "no-info-id",
ctx: testCtxNoInfoId,
e: testError,
e: &testError,
info: &event.RequestInfo{},
setup: func() error {
return event.InitSysEventer(hclog.Default(), c.EventerConfig)
@@ -836,7 +838,7 @@ func Test_WriteError(t *testing.T) {
{
name: "simple",
ctx: testCtx,
e: testError,
e: &testError,
info: info,
errSinkFileName: c.ErrorEvents.Name(),
},
@@ -870,35 +872,24 @@ func Test_WriteError(t *testing.T) {
err = json.Unmarshal(b, gotError)
require.NoErrorf(err, "json: %s", string(b))
actualJson, err := json.Marshal(gotError)
require.NoError(err)
wantError := eventJson{
CreatedAt: gotError.CreatedAt,
EventType: string(gotError.EventType),
Payload: map[string]interface{}{
"error": map[string]interface{}{
"Code": tt.e.(*errors.Err).Code,
"Msg": tt.e.(*errors.Err).Msg,
"Op": tt.e.(*errors.Err).Op,
"Wrapped": tt.e.(*errors.Err).Wrapped,
},
"id": gotError.Payload["id"],
"op": op,
"version": testErrorVersion,
},
actualError := fakeError{
Msg: gotError.Payload["error"].(map[string]interface{})["Msg"].(string),
Code: gotError.Payload["error"].(map[string]interface{})["Code"].(string),
}
if tt.info != nil && tt.info.Id != "" {
wantError.Payload["id"] = tt.info.Id
}
if tt.info != nil {
wantError.Payload["request_info"] = tt.info
}
wantJson, err := json.Marshal(wantError)
require.NoError(err)
assert.Equal(tt.e, &actualError)
assert.JSONEq(string(wantJson), string(actualJson))
}
})
}
}
type fakeError struct {
Code string
Msg string
}
func (f *fakeError) Error() string {
return f.Msg
}
+12
View File
@@ -0,0 +1,12 @@
package event
import (
"errors"
)
var (
ErrInvalidParameter = errors.New("invalid parameter")
ErrMaxRetries = errors.New("too many retries")
ErrIo = errors.New("error during io operation")
ErrRecordNotFound = errors.New("record not found")
)
+10 -11
View File
@@ -4,7 +4,6 @@ import (
"fmt"
"time"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
)
@@ -35,14 +34,14 @@ type audit struct {
func newAudit(fromOperation Op, opt ...Option) (*audit, error) {
const op = "event.newAudit"
if fromOperation == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing from operation")
return nil, fmt.Errorf("%s: missing from operation: %w", op, ErrInvalidParameter)
}
opts := getOpts(opt...)
if opts.withId == "" {
var err error
opts.withId, err = newId(string(AuditType))
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
}
var dtm time.Time
@@ -65,7 +64,7 @@ func newAudit(fromOperation Op, opt ...Option) (*audit, error) {
Flush: opts.withFlush,
}
if err := a.validate(); err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
return a, nil
}
@@ -76,7 +75,7 @@ func (a *audit) EventType() string { return string(AuditType) }
func (a *audit) validate() error {
const op = "event.(audit).validate"
if a.Id == "" {
return errors.New(errors.InvalidParameter, op, "missing id")
return fmt.Errorf("%s: missing id: %w", op, ErrInvalidParameter)
}
return nil
}
@@ -98,31 +97,31 @@ func (a *audit) FlushEvent() bool {
func (a *audit) ComposeFrom(events []*eventlogger.Event) (eventlogger.EventType, interface{}, error) {
const op = "event.(audit).ComposedFrom"
if len(events) == 0 {
return "", nil, errors.New(errors.InvalidParameter, op, "missing events")
return "", nil, fmt.Errorf("%s: missing events: %w", op, ErrInvalidParameter)
}
var validId string
payload := audit{}
for i, v := range events {
gated, ok := v.Payload.(*audit)
if !ok {
return "", nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("event %d is not an audit payload", i))
return "", nil, fmt.Errorf("%s: event %d is not an audit payload: %w", op, i, ErrInvalidParameter)
}
if gated.Id == "" {
// can't really happen since it has to have an id to be gated, but
// I'll add this check in the name of completeness
return "", nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("event %d: id is required", i))
return "", nil, fmt.Errorf("%s: event %d: id is required: %w", op, i, ErrInvalidParameter)
}
if validId == "" {
validId = gated.Id
}
if gated.Id != validId {
return "", nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("event %d has an invalid id: %s != %s", i, gated.Id, validId))
return "", nil, fmt.Errorf("%s: event %d has an invalid id: %s != %s: %w", op, i, gated.Id, validId, ErrInvalidParameter)
}
if gated.Version != auditVersion {
return "", nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("event %d has an invalid version: %s != %s", i, gated.Version, auditVersion))
return "", nil, fmt.Errorf("%s: event %d has an invalid version: %s != %s: %w", op, i, gated.Version, auditVersion, ErrInvalidParameter)
}
if gated.Type != string(apiRequest) {
return "", nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("event %d has an invalid type: %s != %s", i, gated.Type, string(AuditType)))
return "", nil, fmt.Errorf("%s: event %d has an invalid type: %s != %s: %w", op, i, gated.Type, string(AuditType), ErrInvalidParameter)
}
if gated.RequestInfo != nil {
payload.RequestInfo = gated.RequestInfo
@@ -4,7 +4,6 @@ import (
"testing"
"time"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -15,15 +14,15 @@ func Test_newAudit(t *testing.T) {
testNow := time.Now()
tests := []struct {
name string
fromOp Op
opts []Option
want *audit
wantErrMatch *errors.Template
name string
fromOp Op
opts []Option
want *audit
wantErrIs error
}{
{
name: "missing-op",
wantErrMatch: errors.T(errors.InvalidParameter),
name: "missing-op",
wantErrIs: ErrInvalidParameter,
},
{
name: "valid-no-opts",
@@ -62,10 +61,10 @@ func Test_newAudit(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := newAudit(tt.fromOp, tt.opts...)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Nil(got)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
return
}
require.NoError(err)
@@ -87,12 +86,12 @@ func TestAudit_validate(t *testing.T) {
tests := []struct {
name string
id string
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-id",
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing id",
},
{
@@ -105,9 +104,9 @@ func TestAudit_validate(t *testing.T) {
assert, require := assert.New(t), require.New(t)
a := audit{Id: tt.id}
err := a.validate()
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -145,12 +144,12 @@ func TestAudit_ComposeFrom(t *testing.T) {
name string
events []*eventlogger.Event
want audit
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-events",
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing events",
},
{
@@ -158,7 +157,7 @@ func TestAudit_ComposeFrom(t *testing.T) {
events: []*eventlogger.Event{{
Payload: struct{}{},
}},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "not an audit payload",
},
{
@@ -172,7 +171,7 @@ func TestAudit_ComposeFrom(t *testing.T) {
},
},
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "invalid type",
},
{
@@ -186,7 +185,7 @@ func TestAudit_ComposeFrom(t *testing.T) {
},
},
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "invalid version",
},
{
@@ -207,7 +206,7 @@ func TestAudit_ComposeFrom(t *testing.T) {
},
},
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "invalid id",
},
{
@@ -259,10 +258,10 @@ func TestAudit_ComposeFrom(t *testing.T) {
assert, require := assert.New(t), require.New(t)
a := &audit{}
gotType, gotAudit, err := a.ComposeFrom(tt.events)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Nil(gotAudit)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -2,8 +2,6 @@ package event
import (
"fmt"
"github.com/hashicorp/boundary/internal/errors"
)
const (
@@ -20,6 +18,6 @@ func (g DeliveryGuarantee) validate() error {
case DefaultDeliveryGuarantee, BestEffort, Enforced:
return nil
default:
return errors.New(errors.InvalidParameter, op, fmt.Sprintf("%s is not a valid delivery guarantee", g))
return fmt.Errorf("%s: %s is not a valid delivery guarantee: %w", op, g, ErrInvalidParameter)
}
}
@@ -3,7 +3,6 @@ package event
import (
"testing"
"github.com/hashicorp/boundary/internal/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -13,13 +12,13 @@ func TestDeliveryGuarantee_validate(t *testing.T) {
tests := []struct {
name string
g DeliveryGuarantee
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "invalid",
g: "invalid",
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "not a valid delivery guarantee",
},
{
@@ -39,9 +38,9 @@ func TestDeliveryGuarantee_validate(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
err := tt.g.validate()
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Truef(errors.Match(tt.wantErrMatch, err), "wanted %q and got %q", tt.wantErrMatch, err)
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
+10 -8
View File
@@ -1,6 +1,8 @@
package event
import "github.com/hashicorp/boundary/internal/errors"
import (
"fmt"
)
// errorVersion defines the version of error events
const errorVersion = "v0.1"
@@ -16,17 +18,17 @@ type err struct {
func newError(fromOperation Op, e error, opt ...Option) (*err, error) {
const op = "event.newError"
if fromOperation == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing operation")
return nil, fmt.Errorf("%s: missing operation: %w", op, ErrInvalidParameter)
}
if e == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing error")
return nil, fmt.Errorf("%s: missing error: %w", op, ErrInvalidParameter)
}
opts := getOpts(opt...)
if opts.withId == "" {
var err error
opts.withId, err = newId(string(ErrorType))
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
}
newErr := &err{
@@ -37,7 +39,7 @@ func newError(fromOperation Op, e error, opt ...Option) (*err, error) {
Error: e,
}
if err := newErr.validate(); err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
return newErr, nil
}
@@ -48,13 +50,13 @@ func (e *err) EventType() string { return string(ErrorType) }
func (e *err) validate() error {
const op = "event.(err).validate"
if e.Id == "" {
return errors.New(errors.InvalidParameter, op, "missing id")
return fmt.Errorf("%s: missing id: %w", op, ErrInvalidParameter)
}
if e.Op == "" {
return errors.New(errors.InvalidParameter, op, "missing operation")
return fmt.Errorf("%s: missing operation: %w", op, ErrInvalidParameter)
}
if e.Error == nil {
return errors.New(errors.InvalidParameter, op, "missing error")
return fmt.Errorf("%s: missing error: %w", op, ErrInvalidParameter)
}
return nil
}
@@ -1,9 +1,9 @@
package event
import (
"fmt"
"testing"
"github.com/hashicorp/boundary/internal/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -17,27 +17,27 @@ func Test_newError(t *testing.T) {
e error
opts []Option
want *err
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-op",
e: errors.New(errors.InvalidParameter, "missing-operation", "missing operation"),
wantErrMatch: errors.T(errors.InvalidParameter),
e: fmt.Errorf("%s, missing operation: %w", "missing-operation", ErrInvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing operation",
},
{
name: "missing-error",
fromOp: Op("missing-error"),
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing error",
},
{
name: "valid-no-opts",
fromOp: Op("valid-no-opts"),
e: errors.New(errors.InvalidParameter, "valid-no-opts", "valid no opts"),
e: fmt.Errorf("%s: valid no opts: %w", "valid-no-opts", ErrInvalidParameter),
want: &err{
Error: errors.New(errors.InvalidParameter, "valid-no-opts", "valid no opts"),
Error: fmt.Errorf("%s: valid no opts: %w", "valid-no-opts", ErrInvalidParameter),
Version: errorVersion,
Op: Op("valid-no-opts"),
},
@@ -45,13 +45,13 @@ func Test_newError(t *testing.T) {
{
name: "valid-all-opts",
fromOp: Op("valid-all-opts"),
e: errors.New(errors.InvalidParameter, "valid-all-opts", "valid all opts"),
e: fmt.Errorf("%s: valid all opts: %w", "valid-all-opts", ErrInvalidParameter),
opts: []Option{
WithId("valid-all-opts"),
WithRequestInfo(TestRequestInfo(t)),
},
want: &err{
Error: errors.New(errors.InvalidParameter, "valid-all-opts", "valid all opts"),
Error: fmt.Errorf("%s: valid all opts: %w", "valid-all-opts", ErrInvalidParameter),
Version: errorVersion,
Op: Op("valid-all-opts"),
Id: "valid-all-opts",
@@ -63,10 +63,10 @@ func Test_newError(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := newError(tt.fromOp, tt.e, tt.opts...)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Nil(got)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -93,28 +93,28 @@ func Test_errvalidate(t *testing.T) {
id string
op Op
want error
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-id",
op: Op("missing-id"),
want: errors.New(errors.InvalidParameter, "missing-id", "missing id"),
wantErrMatch: errors.T(errors.InvalidParameter),
want: fmt.Errorf("%s: missing id: %w", "missing-id", ErrInvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing id",
},
{
name: "missing-operation",
id: "missing-operation",
want: errors.New(errors.InvalidParameter, "missing-operation", "missing operation"),
wantErrMatch: errors.T(errors.InvalidParameter),
want: fmt.Errorf("%s: missing operation: %w", "missing-operation", ErrInvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing operation",
},
{
name: "valid",
op: Op("valid"),
id: "valid",
want: errors.New(errors.InvalidParameter, "valid", "valid error"),
want: fmt.Errorf("%s: valid error: %w", "valid-error", ErrInvalidParameter),
},
}
for _, tt := range tests {
@@ -126,9 +126,9 @@ func Test_errvalidate(t *testing.T) {
Error: tt.want,
}
err := e.validate()
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -3,7 +3,6 @@ package event
import (
"fmt"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/vault/sdk/helper/strutil"
)
@@ -21,19 +20,19 @@ type observation struct {
func newObservation(fromOperation Op, opt ...Option) (*observation, error) {
const op = "event.newObservation"
if fromOperation == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing operation")
return nil, fmt.Errorf("%s: missing operation: %w", op, ErrInvalidParameter)
}
opts := getOpts(opt...)
if opts.withId == "" {
var err error
opts.withId, err = newId(string(ObservationType))
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
}
for k := range opts.withHeader {
if strutil.StrListContains([]string{OpField, VersionField, RequestInfoField}, k) {
return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("%s is a reserved field name", k))
return nil, fmt.Errorf("%s: %s is a reserved field name: %w", op, k, ErrInvalidParameter)
}
}
i := &observation{
@@ -48,7 +47,7 @@ func newObservation(fromOperation Op, opt ...Option) (*observation, error) {
Version: observationVersion,
}
if err := i.validate(); err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
return i, nil
}
@@ -59,10 +58,10 @@ func (i *observation) EventType() string { return string(ObservationType) }
func (i *observation) validate() error {
const op = "event.(Observation).validate"
if i.ID == "" {
return errors.New(errors.InvalidParameter, op, "missing id")
return fmt.Errorf("%s: missing id: %w", op, ErrInvalidParameter)
}
if i.Op == "" {
return errors.New(errors.InvalidParameter, op, "missing operation")
return fmt.Errorf("%s: missing operation: %w", op, ErrInvalidParameter)
}
return nil
}
@@ -4,7 +4,6 @@ import (
"testing"
"time"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -29,12 +28,12 @@ func Test_newObservation(t *testing.T) {
fromOp Op
opts []Option
want *observation
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-op",
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing operation",
},
{
@@ -73,10 +72,10 @@ func Test_newObservation(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := newObservation(tt.fromOp, tt.opts...)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Nil(got)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -99,19 +98,19 @@ func Test_observationvalidate(t *testing.T) {
name string
id string
op Op
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
name: "missing-id",
op: Op("missing-id"),
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing id",
},
{
name: "missing-operation",
id: "missing-operation",
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing operation",
},
{
@@ -130,9 +129,9 @@ func Test_observationvalidate(t *testing.T) {
},
}
err := e.validate()
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
+1 -3
View File
@@ -2,8 +2,6 @@ package event
import (
"fmt"
"github.com/hashicorp/boundary/internal/errors"
)
// Type represents the event's type
@@ -22,6 +20,6 @@ func (et Type) validate() error {
case EveryType, ObservationType, AuditType, ErrorType:
return nil
default:
return errors.New(errors.InvalidParameter, op, fmt.Sprintf("'%s' is not a valid event type", et))
return fmt.Errorf("%s: '%s' is not a valid event type: %w", op, et, ErrInvalidParameter)
}
}
+31 -32
View File
@@ -7,7 +7,6 @@ import (
"sync"
"time"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog"
)
@@ -63,14 +62,14 @@ var (
func InitSysEventer(log hclog.Logger, c EventerConfig) error {
const op = "event.InitSysEventer"
if log == nil {
return errors.New(errors.InvalidParameter, op, "missing hclog")
return fmt.Errorf("%s: missing hclog: %w", op, ErrInvalidParameter)
}
// the order of operations is important here. we want to determine if
// there's an error before setting the singleton sysEventer which can only
// be done one time.
eventer, err := NewEventer(log, c)
if err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
sysEventerOnce.Do(func() {
sysEventer = eventer
@@ -87,7 +86,7 @@ func SysEventer() *Eventer {
func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, error) {
const op = "event.NewEventer"
if log == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing logger")
return nil, fmt.Errorf("%s: missing logger: %w", op, ErrInvalidParameter)
}
// if there are no sinks in config, then we'll default to just one stdout
@@ -102,7 +101,7 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
}
if err := c.validate(); err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
type pipeline struct {
@@ -134,13 +133,13 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
// Create JSONFormatter node
id, err := newId("json")
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
jsonfmtId := eventlogger.NodeID(id)
fmtNode := &eventlogger.JSONFormatter{}
err = e.broker.RegisterNode(jsonfmtId, fmtNode)
if err != nil {
return nil, errors.Wrap(err, "failed to register json node")
return nil, fmt.Errorf("%s: failed to register json node: %w", op, err)
}
for _, s := range c.Sinks {
@@ -154,7 +153,7 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
}
id, err = newId("stdout")
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
sinkId = eventlogger.NodeID(id)
default:
@@ -168,13 +167,13 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
}
id, err = newId(fmt.Sprintf("file_%s_%s_", s.Path, s.FileName))
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
sinkId = eventlogger.NodeID(id)
}
err = e.broker.RegisterNode(sinkId, sinkNode)
if err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed to register sink node %s", sinkId)))
return nil, fmt.Errorf("%s: failed to register sink node %s: %w", op, sinkId, err)
}
var addToAudit, addToObservation, addToErr bool
for _, t := range s.EventTypes {
@@ -214,10 +213,10 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
}
}
if c.AuditEnabled && len(auditPipelines) == 0 {
return nil, errors.New(errors.InvalidParameter, op, "audit events enabled but no sink defined for it")
return nil, fmt.Errorf("%s: audit events enabled but no sink defined for it: %w", op, ErrInvalidParameter)
}
if c.ObservationsEnabled && len(observationPipelines) == 0 {
return nil, errors.New(errors.InvalidParameter, op, "observation events enabled but no sink defined for it")
return nil, fmt.Errorf("%s: observation events enabled but no sink defined for it: %w", op, ErrInvalidParameter)
}
auditNodeIds := make([]eventlogger.NodeID, 0, len(auditPipelines))
@@ -226,16 +225,16 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
e.flushableNodes = append(e.flushableNodes, &gatedFilterNode)
gateId, err := newId("gated-audit")
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
gatedFilterNodeId := eventlogger.NodeID(gateId)
if err := e.broker.RegisterNode(gatedFilterNodeId, &gatedFilterNode); err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg("unable to register audit gated filter"))
return nil, fmt.Errorf("%s: unable to register audit gated filter: %w", op, err)
}
pipeId, err := newId(auditPipeline)
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
err = e.broker.RegisterPipeline(eventlogger.Pipeline{
EventType: eventlogger.EventType(p.eventType),
@@ -243,7 +242,7 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
NodeIDs: []eventlogger.NodeID{gatedFilterNodeId, p.fmtId, p.sinkId},
})
if err != nil {
return nil, errors.Wrap(err, "failed to register audit pipeline")
return nil, fmt.Errorf("%s: failed to register audit pipeline: %w", op, err)
}
auditNodeIds = append(auditNodeIds, p.sinkId)
}
@@ -253,16 +252,16 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
e.flushableNodes = append(e.flushableNodes, &gatedFilterNode)
gateId, err := newId("gated-observation")
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
gatedFilterNodeId := eventlogger.NodeID(gateId)
if err := e.broker.RegisterNode(gatedFilterNodeId, &gatedFilterNode); err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg("unable to register audit gated filter"))
return nil, fmt.Errorf("%s: unable to register audit gated filter: %w", op, err)
}
pipeId, err := newId(observationPipeline)
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
err = e.broker.RegisterPipeline(eventlogger.Pipeline{
EventType: eventlogger.EventType(p.eventType),
@@ -270,7 +269,7 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
NodeIDs: []eventlogger.NodeID{gatedFilterNodeId, p.fmtId, p.sinkId},
})
if err != nil {
return nil, errors.Wrap(err, "failed to register observation pipeline")
return nil, fmt.Errorf("%s: failed to register observation pipeline: %w", op, err)
}
observationNodeIds = append(observationNodeIds, p.sinkId)
}
@@ -278,7 +277,7 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
for _, p := range errPipelines {
pipeId, err := newId(errPipeline)
if err != nil {
return nil, errors.Wrap(err, op)
return nil, fmt.Errorf("%s: %w", op, err)
}
err = e.broker.RegisterPipeline(eventlogger.Pipeline{
EventType: eventlogger.EventType(p.eventType),
@@ -286,7 +285,7 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
NodeIDs: []eventlogger.NodeID{p.fmtId, p.sinkId},
})
if err != nil {
return nil, errors.Wrap(err, "failed to register err pipeline")
return nil, fmt.Errorf("%s: failed to register err pipeline: %w", op, err)
}
errNodeIds = append(errNodeIds, p.sinkId)
}
@@ -297,19 +296,19 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
if c.AuditDelivery == Enforced {
err = e.broker.SetSuccessThreshold(eventlogger.EventType(AuditType), len(auditNodeIds))
if err != nil {
return nil, errors.Wrap(err, "failed to set success threshold for audit events")
return nil, fmt.Errorf("%s: failed to set success threshold for audit events: %w", op, err)
}
}
if c.ObservationDelivery == Enforced {
err = e.broker.SetSuccessThreshold(eventlogger.EventType(ObservationType), len(observationNodeIds))
if err != nil {
return nil, errors.Wrap(err, "failed to set success threshold for observation events")
return nil, fmt.Errorf("%s: failed to set success threshold for observation events: %w", op, err)
}
}
// always enforce delivery of errors
err = e.broker.SetSuccessThreshold(eventlogger.EventType(ErrorType), len(errNodeIds))
if err != nil {
return nil, errors.Wrap(err, "failed to set success threshold for error events")
return nil, fmt.Errorf("%s: failed to set success threshold for error events: %w", op, err)
}
return e, nil
@@ -319,7 +318,7 @@ func NewEventer(log hclog.Logger, c EventerConfig, opt ...Option) (*Eventer, err
func (e *Eventer) writeObservation(ctx context.Context, event *observation) error {
const op = "event.(Eventer).writeObservation"
if event == nil {
return errors.New(errors.InvalidParameter, op, "missing event")
return fmt.Errorf("%s: missing event: %w", op, ErrInvalidParameter)
}
if !e.conf.ObservationsEnabled {
return nil
@@ -336,7 +335,7 @@ func (e *Eventer) writeObservation(ctx context.Context, event *observation) erro
})
if err != nil {
e.logger.Error("encountered an error sending an observation event", "error:", err.Error())
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
@@ -345,14 +344,14 @@ func (e *Eventer) writeObservation(ctx context.Context, event *observation) erro
func (e *Eventer) writeError(ctx context.Context, event *err) error {
const op = "event.(Eventer).writeError"
if event == nil {
return errors.New(errors.InvalidParameter, op, "missing event")
return fmt.Errorf("%s: missing event: %w", op, ErrInvalidParameter)
}
err := e.retrySend(ctx, stdRetryCount, expBackoff{}, func() (eventlogger.Status, error) {
return e.broker.Send(ctx, eventlogger.EventType(ErrorType), event)
})
if err != nil {
e.logger.Error("encountered an error sending an error event", "error:", err.Error())
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
@@ -361,7 +360,7 @@ func (e *Eventer) writeError(ctx context.Context, event *err) error {
func (e *Eventer) writeAudit(ctx context.Context, event *audit) error {
const op = "event.(Eventer).writeAudit"
if event == nil {
return errors.New(errors.InvalidParameter, op, "missing event")
return fmt.Errorf("%s: missing event: %w", op, ErrInvalidParameter)
}
if !e.conf.AuditEnabled {
return nil
@@ -371,7 +370,7 @@ func (e *Eventer) writeAudit(ctx context.Context, event *audit) error {
})
if err != nil {
e.logger.Error("encountered an error sending an audit event", "error:", err.Error())
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
@@ -391,7 +390,7 @@ func (e *Eventer) FlushNodes(ctx context.Context) error {
const op = "event.(Eventer).FlushNodes"
for _, n := range e.flushableNodes {
if err := n.FlushAll(ctx); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
}
return nil
@@ -2,8 +2,6 @@ package event
import (
"fmt"
"github.com/hashicorp/boundary/internal/errors"
)
// EventerConfig supplies all the configuration needed to create/config an Eventer.
@@ -21,14 +19,14 @@ func (c *EventerConfig) validate() error {
const op = "event.(EventerConfig).validate"
if err := c.AuditDelivery.validate(); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
if err := c.ObservationDelivery.validate(); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
for i, s := range c.Sinks {
if err := s.validate(); err != nil {
return errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("sink %d is invalid", i)))
return fmt.Errorf("%s: sink %d is invalid: %w", op, i, err)
}
}
return nil
@@ -3,7 +3,6 @@ package event
import (
"testing"
"github.com/hashicorp/boundary/internal/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -12,7 +11,7 @@ func TestEventerConfig_validate(t *testing.T) {
tests := []struct {
name string
c EventerConfig
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
@@ -20,7 +19,7 @@ func TestEventerConfig_validate(t *testing.T) {
c: EventerConfig{
AuditDelivery: "invalid",
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "is not a valid delivery guarantee",
},
{
@@ -34,7 +33,7 @@ func TestEventerConfig_validate(t *testing.T) {
c: EventerConfig{
ObservationDelivery: "invalid",
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "is not a valid delivery guarantee",
},
{
@@ -52,7 +51,7 @@ func TestEventerConfig_validate(t *testing.T) {
},
},
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "is not a valid sink type",
},
{
@@ -65,9 +64,9 @@ func TestEventerConfig_validate(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
err := tt.c.validate()
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Truef(errors.Match(tt.wantErrMatch, err), "wanted %q and got %q", tt.wantErrMatch, err)
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
@@ -7,7 +7,6 @@ import (
"math/rand"
"time"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-multierror"
)
@@ -41,10 +40,10 @@ type sendHandler func() (eventlogger.Status, error)
func (e *Eventer) retrySend(ctx context.Context, retries uint, backOff backoff, handler sendHandler) error {
const op = "event.(Eventer).retrySend"
if backOff == nil {
return errors.New(errors.InvalidParameter, op, "missing backoff")
return fmt.Errorf("%s: missing backoff: %w", op, ErrInvalidParameter)
}
if handler == nil {
return errors.New(errors.InvalidParameter, op, "missing handler")
return fmt.Errorf("%s: missing handler: %w", op, ErrInvalidParameter)
}
success := false
var retryErrors error
@@ -52,7 +51,7 @@ func (e *Eventer) retrySend(ctx context.Context, retries uint, backOff backoff,
info := retryInfo{}
for attempts := uint(1); ; attempts++ {
if attempts > retries+1 {
retryErrors = multierror.Append(retryErrors, errors.New(errors.MaxRetries, op, fmt.Sprintf("Too many retries: reached max of %d", retries)))
retryErrors = multierror.Append(retryErrors, fmt.Errorf("%s: reached max of %d: %w", op, retries, ErrMaxRetries))
return retryErrors
}
var err error
@@ -65,7 +64,7 @@ func (e *Eventer) retrySend(ctx context.Context, retries uint, backOff backoff,
e.logger.Error("unable to send event", "operation", op, "warning", retryWarnings)
}
if err != nil {
retryErrors = multierror.Append(retryErrors, errors.Wrap(err, op))
retryErrors = multierror.Append(retryErrors, fmt.Errorf("%s: %w", op, err))
d := backOff.duration(attempts)
info.retries++
info.backoff = info.backoff + d
@@ -76,7 +75,7 @@ func (e *Eventer) retrySend(ctx context.Context, retries uint, backOff backoff,
break
}
if !success {
return errors.Wrap(retryErrors, op, errors.WithMsg("failed to send event"))
return fmt.Errorf("%s: failed to send event: %w", op, retryErrors)
}
return nil
}
@@ -2,10 +2,10 @@ package event
import (
"context"
"fmt"
"os"
"testing"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror"
@@ -22,7 +22,7 @@ func TestEventer_retrySend(t *testing.T) {
eventer, err := NewEventer(hclog.Default(), testConfig.EventerConfig)
require.NoError(t, err)
testError := errors.New(errors.InvalidParameter, "missing-operation", "missing operation")
testError := fmt.Errorf("%s: missing operation: %w", "missing operation", ErrInvalidParameter)
testEvent, err := newError("TestEventer_retrySend", testError, WithId("test-error"))
require.NoError(t, err)
@@ -31,7 +31,7 @@ func TestEventer_retrySend(t *testing.T) {
retries uint
backOff backoff
handler sendHandler
wantErrMatch *errors.Template
wantErrIs error
wantErrContain string
}{
{
@@ -40,14 +40,14 @@ func TestEventer_retrySend(t *testing.T) {
handler: func() (eventlogger.Status, error) {
return eventer.broker.Send(ctx, eventlogger.EventType(ErrorType), testEvent)
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContain: "missing backoff",
},
{
name: "missing-handler",
retries: 1,
backOff: expBackoff{},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContain: "missing handler",
},
{
@@ -55,10 +55,10 @@ func TestEventer_retrySend(t *testing.T) {
retries: 3,
backOff: expBackoff{},
handler: func() (eventlogger.Status, error) {
return eventlogger.Status{}, errors.New(errors.InvalidParameter, "TestEventer_retrySend", "will never work")
return eventlogger.Status{}, fmt.Errorf("%s: will never work: %w", "TestEventer_retrySend", ErrMaxRetries)
},
wantErrMatch: errors.T(errors.MaxRetries),
wantErrContain: "Too many retries",
wantErrIs: ErrMaxRetries,
wantErrContain: "too many retries",
},
{
name: "success-with-warnings",
@@ -66,7 +66,7 @@ func TestEventer_retrySend(t *testing.T) {
backOff: expBackoff{},
handler: func() (eventlogger.Status, error) {
return eventlogger.Status{
Warnings: []error{errors.New(errors.RecordNotFound, "TestEventer_retrySend", "not found")},
Warnings: []error{fmt.Errorf("%s: not found: %w", "TestEventer_retrySend", ErrRecordNotFound)},
}, nil
},
},
@@ -87,14 +87,14 @@ func TestEventer_retrySend(t *testing.T) {
defer os.Remove(testConfig.ErrorEvents.Name())
err := eventer.retrySend(ctx, tt.retries, tt.backOff, tt.handler)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
multi, isMultiError := err.(*multierror.Error)
switch isMultiError {
case true:
matched := false
for _, e := range multi.WrappedErrors() {
if errors.Match(tt.wantErrMatch, e) {
if assert.ErrorIs(e, tt.wantErrIs) {
if tt.wantErrContain != "" {
assert.Contains(err.Error(), tt.wantErrContain)
}
@@ -103,7 +103,7 @@ func TestEventer_retrySend(t *testing.T) {
}
assert.True(matched)
default:
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContain != "" {
assert.Contains(err.Error(), tt.wantErrContain)
}
+60 -62
View File
@@ -2,10 +2,10 @@ package event
import (
"context"
"fmt"
"strings"
"testing"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/assert"
@@ -18,17 +18,17 @@ func Test_InitSysEventer(t *testing.T) {
testConfig := TestEventerConfig(t, "InitSysEventer")
tests := []struct {
name string
log hclog.Logger
config EventerConfig
want *Eventer
wantErrMatch *errors.Template
name string
log hclog.Logger
config EventerConfig
want *Eventer
wantErrIs error
}{
{
name: "missing-hclog",
config: testConfig.EventerConfig,
wantErrMatch: errors.T(errors.InvalidParameter),
name: "missing-hclog",
config: testConfig.EventerConfig,
wantErrIs: ErrInvalidParameter,
},
{
name: "success",
@@ -66,12 +66,10 @@ func Test_InitSysEventer(t *testing.T) {
err := InitSysEventer(tt.log, tt.config)
got := SysEventer()
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Nil(got)
require.Error(err)
if tt.wantErrMatch != nil {
assert.True(errors.Match(tt.wantErrMatch, err))
}
assert.ErrorIs(err, tt.wantErrIs)
return
}
require.NoError(err)
@@ -96,21 +94,21 @@ func TestEventer_writeObservation(t *testing.T) {
require.NoError(t, err)
tests := []struct {
name string
broker broker
observation *observation
wantErrMatch *errors.Template
name string
broker broker
observation *observation
wantErrIs error
}{
{
name: "missing-observation",
broker: &testMockBroker{},
wantErrMatch: errors.T(errors.InvalidParameter),
name: "missing-observation",
broker: &testMockBroker{},
wantErrIs: ErrInvalidParameter,
},
{
name: "send-fails",
broker: &testMockBroker{errorOnSend: errors.New(errors.Io, "test", "no msg")},
observation: testObservation,
wantErrMatch: errors.T(errors.Io),
name: "send-fails",
broker: &testMockBroker{errorOnSend: fmt.Errorf("%s: no msg: %w", "test", ErrIo)},
observation: testObservation,
wantErrIs: ErrMaxRetries,
},
{
name: "success",
@@ -125,9 +123,9 @@ func TestEventer_writeObservation(t *testing.T) {
eventer.broker = tt.broker
err = eventer.writeObservation(ctx, tt.observation)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Truef(errors.Match(tt.wantErrMatch, err), "got %q and wanted %q", err.Error(), tt.wantErrMatch)
assert.ErrorIs(err, tt.wantErrIs)
return
}
require.NoError(err)
@@ -173,21 +171,21 @@ func TestEventer_writeAudit(t *testing.T) {
require.NoError(t, err)
tests := []struct {
name string
broker broker
audit *audit
wantErrMatch *errors.Template
name string
broker broker
audit *audit
wantErrIs error
}{
{
name: "missing-audit",
broker: &testMockBroker{},
wantErrMatch: errors.T(errors.InvalidParameter),
name: "missing-audit",
broker: &testMockBroker{},
wantErrIs: ErrInvalidParameter,
},
{
name: "send-fails",
broker: &testMockBroker{errorOnSend: errors.New(errors.Io, "test", "no msg")},
audit: testAudit,
wantErrMatch: errors.T(errors.Io),
name: "send-fails",
broker: &testMockBroker{errorOnSend: fmt.Errorf("%s: no msg: %w", "test", ErrIo)},
audit: testAudit,
wantErrIs: ErrIo,
},
{
name: "success",
@@ -202,9 +200,9 @@ func TestEventer_writeAudit(t *testing.T) {
eventer.broker = tt.broker
err = eventer.writeAudit(ctx, tt.audit)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Truef(errors.Match(tt.wantErrMatch, err), "got %q and wanted %q", err.Error(), tt.wantErrMatch)
assert.ErrorIs(err, tt.wantErrIs)
return
}
require.NoError(err)
@@ -219,25 +217,25 @@ func TestEventer_writeError(t *testing.T) {
eventer, er := NewEventer(hclog.Default(), testSetup.EventerConfig)
require.NoError(t, er)
testError, er := newError("TestEventer_writeError", errors.New(errors.Io, "test", "no msg"))
testError, er := newError("TestEventer_writeError", fmt.Errorf("%s: no msg: test", ErrIo))
require.NoError(t, er)
tests := []struct {
name string
broker broker
err *err
wantErrMatch *errors.Template
name string
broker broker
err *err
wantErrIs error
}{
{
name: "missing-error",
broker: &testMockBroker{},
wantErrMatch: errors.T(errors.InvalidParameter),
name: "missing-error",
broker: &testMockBroker{},
wantErrIs: ErrInvalidParameter,
},
{
name: "send-fails",
broker: &testMockBroker{errorOnSend: errors.New(errors.Io, "test", "no msg")},
err: testError,
wantErrMatch: errors.T(errors.Io),
name: "send-fails",
broker: &testMockBroker{errorOnSend: fmt.Errorf("%s: no msg: test", ErrIo)},
err: testError,
wantErrIs: ErrMaxRetries,
},
{
name: "success",
@@ -252,9 +250,9 @@ func TestEventer_writeError(t *testing.T) {
eventer.broker = tt.broker
err := eventer.writeError(ctx, tt.err)
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
assert.Truef(errors.Match(tt.wantErrMatch, err), "got %q and wanted %q", err.Error(), tt.wantErrMatch)
assert.ErrorIs(err, tt.wantErrIs)
return
}
require.NoError(err)
@@ -277,20 +275,20 @@ func Test_NewEventer(t *testing.T) {
wantRegistered []string
wantPipelines []string
wantThresholds map[eventlogger.EventType]int
wantErrMatch *errors.Template
wantErrIs error
}{
{
name: "invalid-config",
config: EventerConfig{
AuditDelivery: "invalid",
},
logger: hclog.Default(),
wantErrMatch: errors.T(errors.InvalidParameter),
logger: hclog.Default(),
wantErrIs: ErrInvalidParameter,
},
{
name: "missing-logger",
config: testSetup.EventerConfig,
wantErrMatch: errors.T(errors.InvalidParameter),
name: "missing-logger",
config: testSetup.EventerConfig,
wantErrIs: ErrInvalidParameter,
},
{
name: "success-with-default-config",
@@ -403,10 +401,10 @@ func Test_NewEventer(t *testing.T) {
assert, require := assert.New(t), require.New(t)
testBroker := &testMockBroker{}
got, err := NewEventer(tt.logger, tt.config, testWithBroker(testBroker))
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
require.Nil(got)
assert.True(errors.Match(tt.wantErrMatch, err))
assert.ErrorIs(err, tt.wantErrIs)
return
}
require.NoError(err)
@@ -486,7 +484,7 @@ type testFlushNode struct {
func (t *testFlushNode) FlushAll(_ context.Context) error {
t.flushed = true
if t.raiseError {
return errors.New(errors.InvalidParameter, "flush-all", "test error")
return fmt.Errorf("%s: test error: flush-all", ErrInvalidParameter)
}
return nil
}
+3 -2
View File
@@ -1,15 +1,16 @@
package event
import (
"fmt"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
)
func newId(prefix string) (string, error) {
const op = "event.newId"
id, err := db.NewPublicId(prefix)
if err != nil {
return "", errors.Wrap(err, op)
return "", fmt.Errorf("%s: %w", op, err)
}
return id, nil
}
+7 -8
View File
@@ -1,9 +1,8 @@
package event
import (
"fmt"
"time"
"github.com/hashicorp/boundary/internal/errors"
)
// SinkConfig defines the configuration for a Eventer sink
@@ -22,23 +21,23 @@ type SinkConfig struct {
func (sc *SinkConfig) validate() error {
const op = "event.(SinkConfig).validate"
if err := sc.SinkType.validate(); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
if err := sc.Format.validate(); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
if sc.SinkType == FileSink && sc.FileName == "" {
return errors.New(errors.InvalidParameter, op, "missing sink file name")
return fmt.Errorf("%s: missing sink file name: %w", op, ErrInvalidParameter)
}
if sc.Name == "" {
return errors.New(errors.InvalidParameter, op, "missing sink name")
return fmt.Errorf("%s: missing sink name: %w", op, ErrInvalidParameter)
}
if len(sc.EventTypes) == 0 {
return errors.New(errors.InvalidParameter, op, "missing event types")
return fmt.Errorf("%s: missing event types: %w", op, ErrInvalidParameter)
}
for _, et := range sc.EventTypes {
if err := et.validate(); err != nil {
return errors.Wrap(err, op)
return fmt.Errorf("%s: %w", op, err)
}
}
return nil
@@ -3,7 +3,6 @@ package event
import (
"testing"
"github.com/hashicorp/boundary/internal/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -13,7 +12,7 @@ func TestSinkConfig_validate(t *testing.T) {
tests := []struct {
name string
sc SinkConfig
wantErrMatch *errors.Template
wantErrIs error
wantErrContains string
}{
{
@@ -24,7 +23,7 @@ func TestSinkConfig_validate(t *testing.T) {
FileName: "tmp.file",
Format: JSONSinkFormat,
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing sink name",
},
{
@@ -35,7 +34,7 @@ func TestSinkConfig_validate(t *testing.T) {
FileName: "tmp.file",
Format: JSONSinkFormat,
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing event types",
},
{
@@ -47,7 +46,7 @@ func TestSinkConfig_validate(t *testing.T) {
FileName: "tmp.file",
Format: JSONSinkFormat,
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "not a valid event type",
},
{
@@ -58,7 +57,7 @@ func TestSinkConfig_validate(t *testing.T) {
FileName: "tmp.file",
Format: JSONSinkFormat,
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "not a valid sink type",
},
{
@@ -70,7 +69,7 @@ func TestSinkConfig_validate(t *testing.T) {
FileName: "tmp.file",
Format: JSONSinkFormat,
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "not a valid sink type",
},
{
@@ -81,7 +80,7 @@ func TestSinkConfig_validate(t *testing.T) {
EventTypes: []Type{EveryType},
FileName: "tmp.file",
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "not a valid sink format",
},
{
@@ -93,7 +92,7 @@ func TestSinkConfig_validate(t *testing.T) {
EventTypes: []Type{EveryType},
FileName: "tmp.file",
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "not a valid sink format",
},
{
@@ -103,7 +102,7 @@ func TestSinkConfig_validate(t *testing.T) {
SinkType: FileSink,
Format: JSONSinkFormat,
},
wantErrMatch: errors.T(errors.InvalidParameter),
wantErrIs: ErrInvalidParameter,
wantErrContains: "missing sink file name",
},
{
@@ -121,9 +120,9 @@ func TestSinkConfig_validate(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
err := tt.sc.validate()
if tt.wantErrMatch != nil {
if tt.wantErrIs != nil {
require.Error(err)
require.Truef(errors.Match(tt.wantErrMatch, err), "wanted %q and got %q", tt.wantErrMatch, err)
assert.ErrorIs(err, tt.wantErrIs)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
+1 -3
View File
@@ -2,8 +2,6 @@ package event
import (
"fmt"
"github.com/hashicorp/boundary/internal/errors"
)
const (
@@ -18,6 +16,6 @@ func (f SinkFormat) validate() error {
case JSONSinkFormat:
return nil
default:
return errors.New(errors.InvalidParameter, op, fmt.Sprintf("'%s' is not a valid sink format", f))
return fmt.Errorf("%s: '%s' is not a valid sink format: %w", op, f, ErrInvalidParameter)
}
}
+1 -3
View File
@@ -2,8 +2,6 @@ package event
import (
"fmt"
"github.com/hashicorp/boundary/internal/errors"
)
const (
@@ -19,6 +17,6 @@ func (t SinkType) validate() error {
case StdoutSink, FileSink:
return nil
default:
return errors.New(errors.InvalidParameter, op, fmt.Sprintf("'%s' is not a valid sink type", t))
return fmt.Errorf("%s: '%s' is not a valid sink type: %w", op, t, ErrInvalidParameter)
}
}