mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-12 09:05:12 +00:00
feat(telemetry): improved instrumentation for observability (#11159)
# Which Problems Are Solved Zitadel did not provide easy correlation between errors, logs, traces and metrics. The configuration for those instrumentations was also not consistent, with some supporting different exporters then others. Implementation and parsing of config was also spaghettified over multiple packages, with awkward parsing and inconsistent naming of options. # How the Problems Are Solved All telemetry is now merged under the name "instrumentation". Why? 1. We thought it was a good idea in the past to call the milestone exporter `Telemtry` in the runtime config. Calling this `TelemetryV2` looks weird. 2. Not everything is a meter and not everything is sent (tele...). 3. It's also [defined](https://opentelemetry.io/docs/concepts/instrumentation/) as such by the OTEL documentation. ## New features - Adds structured, context based logging with trace-ID awareness - Static log fields are added to the context, such as service and request path - Static log fields are injected in each logline emitted by the application - Structured logs can also be send to an otel exporter - Structured logs can be printed to StdErr in text and JSON format - Error sinks make sure every error is logged at the correct level: - Warnings for client side errors (HTTP 400 range, Invalid request etc) - Error for server side errors (Internal server errors) - Metrics can now also be send to a OTEL collector. (previously they could only be scraped from `/debug/metrics` with prometheus) ## Exporters This change adds all the exporters supported by OTEL upstream and some google specific exporters for our cloud deployment. - StdOut / StdErr: all instrumentations - OTEL gRPC / HTTP: all instrumentations - Google: all instrumentations except logging - Prometheus (pull-based): only metrics The exception is profiling, which only supports the google exporting due to lack of support by OTEL upstream. ## Configuration and structure - All instrumentation is moved into the new `backend/v3/instrumentation` package. It reuses configuration types, so both code and runtime configuration are easier to understand. - The `internal/telemetry` packages are removed. - Instrumentation is started with a single function and a proper shutdown function is now provided. - Legacy configuration is still parsed from the runtime config, as long as the new configuration is disabled. This allows backporting this feature to v4 without breaking existing configurations. # Additional Changes - Devcontainer: set `$PATH` variable so installed go binaries can be run individually, without NX. - NX: install GCI tool to fix imports # Additional Context - Closes https://github.com/zitadel/zitadel/issues/8408 - Closes https://github.com/zitadel/zitadel/issues/6664 - Backport to v4
This commit is contained in:
@@ -2,43 +2,15 @@ package zerrors
|
||||
|
||||
import "fmt"
|
||||
|
||||
var (
|
||||
_ AlreadyExists = (*AlreadyExistsError)(nil)
|
||||
_ Error = (*AlreadyExistsError)(nil)
|
||||
)
|
||||
|
||||
type AlreadyExists interface {
|
||||
error
|
||||
IsAlreadyExists()
|
||||
}
|
||||
|
||||
type AlreadyExistsError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
|
||||
func ThrowAlreadyExists(parent error, id, message string) error {
|
||||
return &AlreadyExistsError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindAlreadyExists, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowAlreadyExistsf(parent error, id, format string, a ...interface{}) error {
|
||||
return &AlreadyExistsError{CreateZitadelError(parent, id, fmt.Sprintf(format, a...))}
|
||||
}
|
||||
|
||||
func (err *AlreadyExistsError) IsAlreadyExists() {}
|
||||
|
||||
func (err *AlreadyExistsError) Is(target error) bool {
|
||||
t, ok := target.(*AlreadyExistsError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
func ThrowAlreadyExistsf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindAlreadyExists, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func IsErrorAlreadyExists(err error) bool {
|
||||
_, ok := err.(AlreadyExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *AlreadyExistsError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindAlreadyExists
|
||||
}
|
||||
|
||||
@@ -9,25 +9,58 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestAlreadyExistsError(t *testing.T) {
|
||||
var alreadyExistsError interface{} = new(zerrors.AlreadyExistsError)
|
||||
_, ok := alreadyExistsError.(zerrors.AlreadyExists)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestAlreadyExists(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowAlreadyExistsf(t *testing.T) {
|
||||
err := zerrors.ThrowAlreadyExistsf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.AlreadyExistsError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowAlreadyExists", func(t *testing.T) {
|
||||
err := zerrors.ThrowAlreadyExists(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsErrorAlreadyExists(t *testing.T) {
|
||||
err := zerrors.ThrowAlreadyExists(nil, "id", "msg")
|
||||
ok := zerrors.IsErrorAlreadyExists(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindAlreadyExists, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("Already Exists!")
|
||||
ok = zerrors.IsErrorAlreadyExists(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowAlreadyExistsf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowAlreadyExistsf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindAlreadyExists, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsErrorAlreadyExists", func(t *testing.T) {
|
||||
err := zerrors.ThrowAlreadyExists(parentErr, id, message)
|
||||
isAlreadyExists := zerrors.IsErrorAlreadyExists(err)
|
||||
assert.True(t, isAlreadyExists)
|
||||
|
||||
otherErr := errors.New("some other error")
|
||||
isAlreadyExists = zerrors.IsErrorAlreadyExists(otherErr)
|
||||
assert.False(t, isAlreadyExists)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ DeadlineExceeded = (*DeadlineExceededError)(nil)
|
||||
_ Error = (*DeadlineExceededError)(nil)
|
||||
)
|
||||
|
||||
type DeadlineExceeded interface {
|
||||
error
|
||||
IsDeadlineExceeded()
|
||||
}
|
||||
|
||||
type DeadlineExceededError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowDeadlineExceeded(parent error, id, message string) error {
|
||||
return &DeadlineExceededError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindDeadlineExceeded, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowDeadlineExceededf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowDeadlineExceeded(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowDeadlineExceededf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindDeadlineExceeded, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *DeadlineExceededError) IsDeadlineExceeded() {}
|
||||
|
||||
func IsDeadlineExceeded(err error) bool {
|
||||
_, ok := err.(DeadlineExceeded)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *DeadlineExceededError) Is(target error) bool {
|
||||
t, ok := target.(*DeadlineExceededError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *DeadlineExceededError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindDeadlineExceeded
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestDeadlineExceededError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.DeadlineExceededError)
|
||||
_, ok := err.(zerrors.DeadlineExceeded)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestDeadlineExceeded(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowDeadlineExceededf(t *testing.T) {
|
||||
err := zerrors.ThrowDeadlineExceededf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.DeadlineExceededError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowDeadlineExceeded", func(t *testing.T) {
|
||||
err := zerrors.ThrowDeadlineExceeded(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsDeadlineExceeded(t *testing.T) {
|
||||
err := zerrors.ThrowDeadlineExceeded(nil, "id", "msg")
|
||||
ok := zerrors.IsDeadlineExceeded(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindDeadlineExceeded, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsDeadlineExceeded(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowDeadlineExceededf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowDeadlineExceededf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindDeadlineExceeded, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsDeadlineExceeded", func(t *testing.T) {
|
||||
err := zerrors.ThrowDeadlineExceeded(parentErr, id, message)
|
||||
isDeadlineExceeded := zerrors.IsDeadlineExceeded(err)
|
||||
assert.True(t, isDeadlineExceeded)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Error is a stdlib error extension.
|
||||
// It contains parameters to identify errors through all application layers
|
||||
type Error interface {
|
||||
GetParent() error
|
||||
GetMessage() string
|
||||
SetMessage(string)
|
||||
GetID() string
|
||||
}
|
||||
|
||||
// Contains compares the error message with needle
|
||||
func Contains(err error, needle string) bool {
|
||||
return err != nil && strings.Contains(err.Error(), needle)
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package zerrors_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
err := errors.New("hello world")
|
||||
world := zerrors.Contains(err, "hello")
|
||||
assert.True(t, world)
|
||||
|
||||
mars := zerrors.Contains(err, "mars")
|
||||
assert.False(t, mars)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ {{.ErrorName}} = (*{{.ErrorName}}Error)(nil)
|
||||
_ Error = (*{{.ErrorName}}Error)(nil)
|
||||
)
|
||||
|
||||
type {{.ErrorName}} interface {
|
||||
error
|
||||
Is{{.ErrorName}}()
|
||||
}
|
||||
|
||||
type {{.ErrorName}}Error struct {
|
||||
*CaosError
|
||||
}
|
||||
|
||||
func Throw{{.ErrorName}}(parent error, id, message string) error {
|
||||
return &{{.ErrorName}}Error{CreateCaosError(parent, id, message)}
|
||||
}
|
||||
|
||||
func Throw{{.ErrorName}}f(parent error, id, format string, a ...interface{}) error {
|
||||
return Throw{{.ErrorName}}(parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *{{.ErrorName}}Error) Is{{.ErrorName}}() {}
|
||||
|
||||
func Is{{.ErrorName}}(err error) bool {
|
||||
_, ok := err.({{.ErrorName}})
|
||||
return ok
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
// go generate
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
errorName := readErrorName()
|
||||
errorName = validateErrorName(errorName)
|
||||
|
||||
data := &Data{
|
||||
ErrorName: errorName,
|
||||
}
|
||||
|
||||
errorFile := data.createFile("error.go.tmpl")
|
||||
data.createTemplate("error.go.tmpl", errorFile)
|
||||
if err := errorFile.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
testFile := data.createFile("error_test.go.tmpl")
|
||||
data.createTemplate("error_test.go.tmpl", testFile)
|
||||
if err := testFile.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Print(`
|
||||
!!!!!
|
||||
Add status mapping in internal/api/grpc/zerrors.go
|
||||
!!!!!`)
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
ErrorName string
|
||||
}
|
||||
|
||||
func (data *Data) createFile(tmplName string) *os.File {
|
||||
filename := strings.Replace(tmplName, "error", strings.ToLower(data.ErrorName), 1)
|
||||
filename = filename[:len(filename)-5]
|
||||
filePath := fmt.Sprintf("../%s", filename)
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to create file (%s): %v", filePath, err)
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
func (data *Data) createTemplate(templateName string, file *os.File) {
|
||||
tmpl := template.Must(template.New(templateName).ParseFiles(templateName))
|
||||
if err := tmpl.Execute(file, data); err != nil {
|
||||
log.Fatal("unable to execute tmpl: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func readErrorName() (errorName string) {
|
||||
flag.StringVar(&errorName, "Name", "", "KeyType of the error (e.g. Internal)")
|
||||
flag.Parse()
|
||||
return errorName
|
||||
}
|
||||
|
||||
func validateErrorName(errorName string) string {
|
||||
if errorName == "" {
|
||||
log.Fatal("pass argument name")
|
||||
}
|
||||
if strings.Contains(errorName, " ") || strings.Contains(errorName, ".") {
|
||||
log.Fatal("name cannot contain spaces or points")
|
||||
}
|
||||
return strings.Title(errorName)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
type {{.ErrorName}} interface {
|
||||
error
|
||||
Is{{.ErrorName}}()
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package errors_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func Test{{.ErrorName}}Error(t *testing.T) {
|
||||
var err interface{}
|
||||
err = new(zerrors.{{.ErrorName}}Error)
|
||||
_, ok := err.(*zerrors.{{.ErrorName}})
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestThrow{{.ErrorName}}f(t *testing.T) {
|
||||
err := zerrors.Throw{{.ErrorName}}f(nil, "id", "msg")
|
||||
_, ok := err.(*zerrors.{{.ErrorName}}Error)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestIs{{.ErrorName}}(t *testing.T) {
|
||||
err := zerrors.Throw{{.ErrorName}}(nil, "id", "msg")
|
||||
ok := zerrors.Is{{.ErrorName}}(err)
|
||||
assert.True(t, ok)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.Is{{.ErrorName}}(err)
|
||||
assert.False(t, ok)
|
||||
}
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Internal = (*InternalError)(nil)
|
||||
_ Error = (*InternalError)(nil)
|
||||
)
|
||||
|
||||
type Internal interface {
|
||||
error
|
||||
IsInternal()
|
||||
}
|
||||
|
||||
type InternalError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowInternal(parent error, id, message string) error {
|
||||
return &InternalError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindInternal, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowInternalf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowInternal(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowInternalf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindInternal, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *InternalError) IsInternal() {}
|
||||
|
||||
func IsInternal(err error) bool {
|
||||
_, ok := err.(Internal)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *InternalError) Is(target error) bool {
|
||||
t, ok := target.(*InternalError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *InternalError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindInternal
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestInternalError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.InternalError)
|
||||
_, ok := err.(zerrors.Internal)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestInternal(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowInternalf(t *testing.T) {
|
||||
err := zerrors.ThrowInternalf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.InternalError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowInternal", func(t *testing.T) {
|
||||
err := zerrors.ThrowInternal(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsInternal(t *testing.T) {
|
||||
err := zerrors.ThrowInternal(nil, "id", "msg")
|
||||
ok := zerrors.IsInternal(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindInternal, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsInternal(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowInternalf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowInternalf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindInternal, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsInternal", func(t *testing.T) {
|
||||
err := zerrors.ThrowInternal(parentErr, id, message)
|
||||
isInternal := zerrors.IsInternal(err)
|
||||
assert.True(t, isInternal)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,55 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ InvalidArgument = (*InvalidArgumentError)(nil)
|
||||
_ Error = (*InvalidArgumentError)(nil)
|
||||
)
|
||||
|
||||
type InvalidArgument interface {
|
||||
error
|
||||
IsInvalidArgument()
|
||||
}
|
||||
|
||||
type InvalidArgumentError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowInvalidArgument(parent error, id, message string) error {
|
||||
return &InvalidArgumentError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindInvalidArgument, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowInvalidArgumentf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowInvalidArgument(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowInvalidArgumentf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindInvalidArgument, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *InvalidArgumentError) IsInvalidArgument() {}
|
||||
|
||||
func IsErrorInvalidArgument(err error) bool {
|
||||
_, ok := err.(InvalidArgument)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *InvalidArgumentError) Is(target error) bool {
|
||||
t, ok := target.(*InvalidArgumentError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *InvalidArgumentError) As(target any) bool {
|
||||
targetErr, ok := target.(*InvalidArgumentError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
*targetErr = *err
|
||||
return true
|
||||
}
|
||||
|
||||
func (err *InvalidArgumentError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindInvalidArgument
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestInvalidArgumentError(t *testing.T) {
|
||||
var invalidArgumentError interface{} = new(zerrors.InvalidArgumentError)
|
||||
_, ok := invalidArgumentError.(zerrors.InvalidArgument)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestInvalidArgument(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowInvalidArgumentf(t *testing.T) {
|
||||
err := zerrors.ThrowInvalidArgumentf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.InvalidArgumentError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowInvalidArgument", func(t *testing.T) {
|
||||
err := zerrors.ThrowInvalidArgument(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsErrorInvalidArgument(t *testing.T) {
|
||||
err := zerrors.ThrowInvalidArgument(nil, "id", "msg")
|
||||
ok := zerrors.IsErrorInvalidArgument(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindInvalidArgument, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am invalid!")
|
||||
ok = zerrors.IsErrorInvalidArgument(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowInvalidArgumentf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowInvalidArgumentf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindInvalidArgument, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsInvalidArgument", func(t *testing.T) {
|
||||
err := zerrors.ThrowInvalidArgument(parentErr, id, message)
|
||||
isInvalidArgument := zerrors.IsErrorInvalidArgument(err)
|
||||
assert.True(t, isInvalidArgument)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
// Code generated by "enumer -type=Kind -trimprefix=Kind -json"; DO NOT EDIT.
|
||||
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const _KindName = "CanceledUnknownInvalidArgumentDeadlineExceededNotFoundAlreadyExistsPermissionDeniedResourceExhaustedPreconditionFailedAbortedOutOfRangeUnimplementedInternalUnavailableDataLossUnauthenticated"
|
||||
|
||||
var _KindIndex = [...]uint8{0, 8, 15, 30, 46, 54, 67, 83, 100, 118, 125, 135, 148, 156, 167, 175, 190}
|
||||
|
||||
const _KindLowerName = "canceledunknowninvalidargumentdeadlineexceedednotfoundalreadyexistspermissiondeniedresourceexhaustedpreconditionfailedabortedoutofrangeunimplementedinternalunavailabledatalossunauthenticated"
|
||||
|
||||
func (i Kind) String() string {
|
||||
i -= 1
|
||||
if i < 0 || i >= Kind(len(_KindIndex)-1) {
|
||||
return fmt.Sprintf("Kind(%d)", i+1)
|
||||
}
|
||||
return _KindName[_KindIndex[i]:_KindIndex[i+1]]
|
||||
}
|
||||
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
func _KindNoOp() {
|
||||
var x [1]struct{}
|
||||
_ = x[KindCanceled-(1)]
|
||||
_ = x[KindUnknown-(2)]
|
||||
_ = x[KindInvalidArgument-(3)]
|
||||
_ = x[KindDeadlineExceeded-(4)]
|
||||
_ = x[KindNotFound-(5)]
|
||||
_ = x[KindAlreadyExists-(6)]
|
||||
_ = x[KindPermissionDenied-(7)]
|
||||
_ = x[KindResourceExhausted-(8)]
|
||||
_ = x[KindPreconditionFailed-(9)]
|
||||
_ = x[KindAborted-(10)]
|
||||
_ = x[KindOutOfRange-(11)]
|
||||
_ = x[KindUnimplemented-(12)]
|
||||
_ = x[KindInternal-(13)]
|
||||
_ = x[KindUnavailable-(14)]
|
||||
_ = x[KindDataLoss-(15)]
|
||||
_ = x[KindUnauthenticated-(16)]
|
||||
}
|
||||
|
||||
var _KindValues = []Kind{KindCanceled, KindUnknown, KindInvalidArgument, KindDeadlineExceeded, KindNotFound, KindAlreadyExists, KindPermissionDenied, KindResourceExhausted, KindPreconditionFailed, KindAborted, KindOutOfRange, KindUnimplemented, KindInternal, KindUnavailable, KindDataLoss, KindUnauthenticated}
|
||||
|
||||
var _KindNameToValueMap = map[string]Kind{
|
||||
_KindName[0:8]: KindCanceled,
|
||||
_KindLowerName[0:8]: KindCanceled,
|
||||
_KindName[8:15]: KindUnknown,
|
||||
_KindLowerName[8:15]: KindUnknown,
|
||||
_KindName[15:30]: KindInvalidArgument,
|
||||
_KindLowerName[15:30]: KindInvalidArgument,
|
||||
_KindName[30:46]: KindDeadlineExceeded,
|
||||
_KindLowerName[30:46]: KindDeadlineExceeded,
|
||||
_KindName[46:54]: KindNotFound,
|
||||
_KindLowerName[46:54]: KindNotFound,
|
||||
_KindName[54:67]: KindAlreadyExists,
|
||||
_KindLowerName[54:67]: KindAlreadyExists,
|
||||
_KindName[67:83]: KindPermissionDenied,
|
||||
_KindLowerName[67:83]: KindPermissionDenied,
|
||||
_KindName[83:100]: KindResourceExhausted,
|
||||
_KindLowerName[83:100]: KindResourceExhausted,
|
||||
_KindName[100:118]: KindPreconditionFailed,
|
||||
_KindLowerName[100:118]: KindPreconditionFailed,
|
||||
_KindName[118:125]: KindAborted,
|
||||
_KindLowerName[118:125]: KindAborted,
|
||||
_KindName[125:135]: KindOutOfRange,
|
||||
_KindLowerName[125:135]: KindOutOfRange,
|
||||
_KindName[135:148]: KindUnimplemented,
|
||||
_KindLowerName[135:148]: KindUnimplemented,
|
||||
_KindName[148:156]: KindInternal,
|
||||
_KindLowerName[148:156]: KindInternal,
|
||||
_KindName[156:167]: KindUnavailable,
|
||||
_KindLowerName[156:167]: KindUnavailable,
|
||||
_KindName[167:175]: KindDataLoss,
|
||||
_KindLowerName[167:175]: KindDataLoss,
|
||||
_KindName[175:190]: KindUnauthenticated,
|
||||
_KindLowerName[175:190]: KindUnauthenticated,
|
||||
}
|
||||
|
||||
var _KindNames = []string{
|
||||
_KindName[0:8],
|
||||
_KindName[8:15],
|
||||
_KindName[15:30],
|
||||
_KindName[30:46],
|
||||
_KindName[46:54],
|
||||
_KindName[54:67],
|
||||
_KindName[67:83],
|
||||
_KindName[83:100],
|
||||
_KindName[100:118],
|
||||
_KindName[118:125],
|
||||
_KindName[125:135],
|
||||
_KindName[135:148],
|
||||
_KindName[148:156],
|
||||
_KindName[156:167],
|
||||
_KindName[167:175],
|
||||
_KindName[175:190],
|
||||
}
|
||||
|
||||
// KindString retrieves an enum value from the enum constants string name.
|
||||
// Throws an error if the param is not part of the enum.
|
||||
func KindString(s string) (Kind, error) {
|
||||
if val, ok := _KindNameToValueMap[s]; ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
if val, ok := _KindNameToValueMap[strings.ToLower(s)]; ok {
|
||||
return val, nil
|
||||
}
|
||||
return 0, fmt.Errorf("%s does not belong to Kind values", s)
|
||||
}
|
||||
|
||||
// KindValues returns all values of the enum
|
||||
func KindValues() []Kind {
|
||||
return _KindValues
|
||||
}
|
||||
|
||||
// KindStrings returns a slice of all String values of the enum
|
||||
func KindStrings() []string {
|
||||
strs := make([]string, len(_KindNames))
|
||||
copy(strs, _KindNames)
|
||||
return strs
|
||||
}
|
||||
|
||||
// IsAKind returns "true" if the value is listed in the enum definition. "false" otherwise
|
||||
func (i Kind) IsAKind() bool {
|
||||
for _, v := range _KindValues {
|
||||
if i == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface for Kind
|
||||
func (i Kind) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(i.String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface for Kind
|
||||
func (i *Kind) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return fmt.Errorf("Kind should be a string, got %s", data)
|
||||
}
|
||||
|
||||
var err error
|
||||
*i, err = KindString(s)
|
||||
return err
|
||||
}
|
||||
@@ -2,38 +2,15 @@ package zerrors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type NotFound interface {
|
||||
error
|
||||
IsNotFound()
|
||||
}
|
||||
|
||||
type NotFoundError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
|
||||
func ThrowNotFound(parent error, id, message string) error {
|
||||
return &NotFoundError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindNotFound, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowNotFoundf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowNotFound(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowNotFoundf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindNotFound, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *NotFoundError) IsNotFound() {}
|
||||
|
||||
func IsNotFound(err error) bool {
|
||||
_, ok := err.(NotFound)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *NotFoundError) Is(target error) bool {
|
||||
t, ok := target.(*NotFoundError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *NotFoundError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindNotFound
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestNotFoundError(t *testing.T) {
|
||||
var notFoundError interface{} = new(zerrors.NotFoundError)
|
||||
_, ok := notFoundError.(zerrors.NotFound)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestNotFound(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowNotFoundf(t *testing.T) {
|
||||
err := zerrors.ThrowNotFoundf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.NotFoundError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowNotFound", func(t *testing.T) {
|
||||
err := zerrors.ThrowNotFound(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsNotFound(t *testing.T) {
|
||||
err := zerrors.ThrowNotFound(nil, "id", "msg")
|
||||
ok := zerrors.IsNotFound(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindNotFound, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsNotFound(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowNotFoundf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowNotFoundf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindNotFound, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsNotFound", func(t *testing.T) {
|
||||
err := zerrors.ThrowNotFound(parentErr, id, message)
|
||||
isNotFound := zerrors.IsNotFound(err)
|
||||
assert.True(t, isNotFound)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ PermissionDenied = (*PermissionDeniedError)(nil)
|
||||
_ Error = (*PermissionDeniedError)(nil)
|
||||
)
|
||||
|
||||
type PermissionDenied interface {
|
||||
error
|
||||
IsPermissionDenied()
|
||||
}
|
||||
|
||||
type PermissionDeniedError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowPermissionDenied(parent error, id, message string) error {
|
||||
return &PermissionDeniedError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindPermissionDenied, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowPermissionDeniedf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowPermissionDenied(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowPermissionDeniedf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindPermissionDenied, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *PermissionDeniedError) IsPermissionDenied() {}
|
||||
|
||||
func IsPermissionDenied(err error) bool {
|
||||
_, ok := err.(PermissionDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *PermissionDeniedError) Is(target error) bool {
|
||||
t, ok := target.(*PermissionDeniedError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *PermissionDeniedError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindPermissionDenied
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestPermissionDeniedError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.PermissionDeniedError)
|
||||
_, ok := err.(zerrors.PermissionDenied)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestPermissionDenied(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "PERMISSION_DENIED"
|
||||
message := "you do not have permission"
|
||||
|
||||
func TestThrowPermissionDeniedf(t *testing.T) {
|
||||
err := zerrors.ThrowPermissionDeniedf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.PermissionDeniedError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowPermissionDenied", func(t *testing.T) {
|
||||
err := zerrors.ThrowPermissionDenied(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsPermissionDenied(t *testing.T) {
|
||||
err := zerrors.ThrowPermissionDenied(nil, "id", "msg")
|
||||
ok := zerrors.IsPermissionDenied(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindPermissionDenied, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsPermissionDenied(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowPermissionDeniedf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowPermissionDeniedf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindPermissionDenied, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsPermissionDenied", func(t *testing.T) {
|
||||
err := zerrors.ThrowPermissionDenied(parentErr, id, message)
|
||||
isPermissionDenied := zerrors.IsPermissionDenied(err)
|
||||
assert.True(t, isPermissionDenied)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ PreconditionFailed = (*PreconditionFailedError)(nil)
|
||||
_ Error = (*PreconditionFailedError)(nil)
|
||||
)
|
||||
|
||||
type PreconditionFailed interface {
|
||||
error
|
||||
IsPreconditionFailed()
|
||||
}
|
||||
|
||||
type PreconditionFailedError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowPreconditionFailed(parent error, id, message string) error {
|
||||
return &PreconditionFailedError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindPreconditionFailed, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowPreconditionFailedf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowPreconditionFailed(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowPreconditionFailedf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindPreconditionFailed, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *PreconditionFailedError) IsPreconditionFailed() {}
|
||||
|
||||
func IsPreconditionFailed(err error) bool {
|
||||
_, ok := err.(PreconditionFailed)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *PreconditionFailedError) Is(target error) bool {
|
||||
t, ok := target.(*PreconditionFailedError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *PreconditionFailedError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindPreconditionFailed
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestPreconditionFailedError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.PreconditionFailedError)
|
||||
_, ok := err.(zerrors.PreconditionFailed)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestPreconditionFailed(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowPreconditionFailedf(t *testing.T) {
|
||||
err := zerrors.ThrowPreconditionFailedf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.PreconditionFailedError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowPreconditionFailed", func(t *testing.T) {
|
||||
err := zerrors.ThrowPreconditionFailed(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsPreconditionFailed(t *testing.T) {
|
||||
err := zerrors.ThrowPreconditionFailed(nil, "id", "msg")
|
||||
ok := zerrors.IsPreconditionFailed(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindPreconditionFailed, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("Precondition failed!")
|
||||
ok = zerrors.IsPreconditionFailed(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowPreconditionFailedf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowPreconditionFailedf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindPreconditionFailed, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsPreconditionFailed", func(t *testing.T) {
|
||||
err := zerrors.ThrowPreconditionFailed(parentErr, id, message)
|
||||
isPreconditionFailed := zerrors.IsPreconditionFailed(err)
|
||||
assert.True(t, isPreconditionFailed)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,48 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ ResourceExhausted = (*ResourceExhaustedError)(nil)
|
||||
_ Error = (*ResourceExhaustedError)(nil)
|
||||
)
|
||||
|
||||
type ResourceExhausted interface {
|
||||
error
|
||||
IsResourceExhausted()
|
||||
}
|
||||
|
||||
type ResourceExhaustedError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowResourceExhausted(parent error, id, message string) error {
|
||||
return &ResourceExhaustedError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindResourceExhausted, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowResourceExhaustedf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowResourceExhausted(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowResourceExhaustedf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindResourceExhausted, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *ResourceExhaustedError) IsResourceExhausted() {}
|
||||
|
||||
func IsResourceExhausted(err error) bool {
|
||||
//nolint:errorlint
|
||||
_, ok := err.(ResourceExhausted)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *ResourceExhaustedError) Is(target error) bool {
|
||||
//nolint:errorlint
|
||||
t, ok := target.(*ResourceExhaustedError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *ResourceExhaustedError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindResourceExhausted
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestResourceExhaustedError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.ResourceExhaustedError)
|
||||
_, ok := err.(zerrors.ResourceExhausted)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestResourceExhausted(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowResourceExhaustedf(t *testing.T) {
|
||||
err := zerrors.ThrowResourceExhaustedf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.ResourceExhaustedError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowResourceExhausted", func(t *testing.T) {
|
||||
err := zerrors.ThrowResourceExhausted(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsResourceExhausted(t *testing.T) {
|
||||
err := zerrors.ThrowResourceExhausted(nil, "id", "msg")
|
||||
ok := zerrors.IsResourceExhausted(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindResourceExhausted, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsResourceExhausted(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowResourceExhaustedf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowResourceExhaustedf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindResourceExhausted, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsResourceExhausted", func(t *testing.T) {
|
||||
err := zerrors.ThrowResourceExhausted(parentErr, id, message)
|
||||
isResourceExhausted := zerrors.IsResourceExhausted(err)
|
||||
assert.True(t, isResourceExhausted)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Unauthenticated = (*UnauthenticatedError)(nil)
|
||||
_ Error = (*UnauthenticatedError)(nil)
|
||||
)
|
||||
|
||||
type Unauthenticated interface {
|
||||
error
|
||||
IsUnauthenticated()
|
||||
}
|
||||
|
||||
type UnauthenticatedError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowUnauthenticated(parent error, id, message string) error {
|
||||
return &UnauthenticatedError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindUnauthenticated, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowUnauthenticatedf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowUnauthenticated(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowUnauthenticatedf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindUnauthenticated, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *UnauthenticatedError) IsUnauthenticated() {}
|
||||
|
||||
func IsUnauthenticated(err error) bool {
|
||||
_, ok := err.(Unauthenticated)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *UnauthenticatedError) Is(target error) bool {
|
||||
t, ok := target.(*UnauthenticatedError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *UnauthenticatedError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindUnauthenticated
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestUnauthenticatedError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.UnauthenticatedError)
|
||||
_, ok := err.(zerrors.Unauthenticated)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestUnauthenticated(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowUnauthenticatedf(t *testing.T) {
|
||||
err := zerrors.ThrowUnauthenticatedf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.UnauthenticatedError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowUnauthenticated", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnauthenticated(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsUnauthenticated(t *testing.T) {
|
||||
err := zerrors.ThrowUnauthenticated(nil, "id", "msg")
|
||||
ok := zerrors.IsUnauthenticated(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnauthenticated, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsUnauthenticated(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowUnauthenticatedf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowUnauthenticatedf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnauthenticated, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsUnauthenticated", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnauthenticated(parentErr, id, message)
|
||||
isUnauthenticated := zerrors.IsUnauthenticated(err)
|
||||
assert.True(t, isUnauthenticated)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Unavailable = (*UnavailableError)(nil)
|
||||
_ Error = (*UnavailableError)(nil)
|
||||
)
|
||||
|
||||
type Unavailable interface {
|
||||
error
|
||||
IsUnavailable()
|
||||
}
|
||||
|
||||
type UnavailableError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowUnavailable(parent error, id, message string) error {
|
||||
return &UnavailableError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindUnavailable, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowUnavailablef(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowUnavailable(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowUnavailablef(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindUnavailable, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *UnavailableError) IsUnavailable() {}
|
||||
|
||||
func IsUnavailable(err error) bool {
|
||||
_, ok := err.(Unavailable)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *UnavailableError) Is(target error) bool {
|
||||
t, ok := target.(*UnavailableError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *UnavailableError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindUnavailable
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestUnavailableError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.UnavailableError)
|
||||
_, ok := err.(zerrors.Unavailable)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestUnavailable(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowUnavailablef(t *testing.T) {
|
||||
err := zerrors.ThrowUnavailablef(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.UnavailableError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowUnavailable", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnavailable(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsUnavailable(t *testing.T) {
|
||||
err := zerrors.ThrowUnavailable(nil, "id", "msg")
|
||||
ok := zerrors.IsUnavailable(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnavailable, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsUnavailable(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowUnavailablef", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowUnavailablef(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnavailable, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsUnavailable", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnavailable(parentErr, id, message)
|
||||
isUnavailable := zerrors.IsUnavailable(err)
|
||||
assert.True(t, isUnavailable)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Unimplemented = (*UnimplementedError)(nil)
|
||||
_ Error = (*UnimplementedError)(nil)
|
||||
)
|
||||
|
||||
type Unimplemented interface {
|
||||
error
|
||||
IsUnimplemented()
|
||||
}
|
||||
|
||||
type UnimplementedError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowUnimplemented(parent error, id, message string) error {
|
||||
return &UnimplementedError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindUnimplemented, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowUnimplementedf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowUnimplemented(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowUnimplementedf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindUnimplemented, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *UnimplementedError) IsUnimplemented() {}
|
||||
|
||||
func IsUnimplemented(err error) bool {
|
||||
_, ok := err.(Unimplemented)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *UnimplementedError) Is(target error) bool {
|
||||
t, ok := target.(*UnimplementedError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *UnimplementedError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindUnimplemented
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestUnimplementedError(t *testing.T) {
|
||||
var unimplementedError interface{} = new(zerrors.UnimplementedError)
|
||||
_, ok := unimplementedError.(zerrors.Unimplemented)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestUnimplemented(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowUnimplementedf(t *testing.T) {
|
||||
err := zerrors.ThrowUnimplementedf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.UnimplementedError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowUnimplemented", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnimplemented(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsUnimplemented(t *testing.T) {
|
||||
err := zerrors.ThrowUnimplemented(nil, "id", "msg")
|
||||
ok := zerrors.IsUnimplemented(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnimplemented, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsUnimplemented(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowUnimplementedf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowUnimplementedf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnimplemented, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsUnimplemented", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnimplemented(parentErr, id, message)
|
||||
isUnimplemented := zerrors.IsUnimplemented(err)
|
||||
assert.True(t, isUnimplemented)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,46 +1,16 @@
|
||||
package zerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Unknown = (*UnknownError)(nil)
|
||||
_ Error = (*UnknownError)(nil)
|
||||
)
|
||||
|
||||
type Unknown interface {
|
||||
error
|
||||
IsUnknown()
|
||||
}
|
||||
|
||||
type UnknownError struct {
|
||||
*ZitadelError
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
func ThrowUnknown(parent error, id, message string) error {
|
||||
return &UnknownError{CreateZitadelError(parent, id, message)}
|
||||
return CreateZitadelError(KindUnknown, parent, id, message)
|
||||
}
|
||||
|
||||
func ThrowUnknownf(parent error, id, format string, a ...interface{}) error {
|
||||
return ThrowUnknown(parent, id, fmt.Sprintf(format, a...))
|
||||
func ThrowUnknownf(parent error, id, format string, a ...any) error {
|
||||
return CreateZitadelError(KindUnknown, parent, id, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (err *UnknownError) IsUnknown() {}
|
||||
|
||||
func IsUnknown(err error) bool {
|
||||
_, ok := err.(Unknown)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err *UnknownError) Is(target error) bool {
|
||||
t, ok := target.(*UnknownError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.ZitadelError.Is(t.ZitadelError)
|
||||
}
|
||||
|
||||
func (err *UnknownError) Unwrap() error {
|
||||
return err.ZitadelError
|
||||
zitadelErr, ok := AsZitadelError(err)
|
||||
return ok && zitadelErr.Kind == KindUnknown
|
||||
}
|
||||
|
||||
@@ -9,25 +9,54 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestUnknownError(t *testing.T) {
|
||||
var err interface{} = new(zerrors.UnknownError)
|
||||
_, ok := err.(zerrors.Unknown)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
func TestUnknown(t *testing.T) {
|
||||
parentErr := errors.New("parent error")
|
||||
id := "test_id"
|
||||
message := "test message"
|
||||
|
||||
func TestThrowUnknownf(t *testing.T) {
|
||||
err := zerrors.ThrowUnknownf(nil, "id", "msg")
|
||||
//nolint:errorlint
|
||||
_, ok := err.(*zerrors.UnknownError)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
t.Run("ThrowUnknown", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnknown(parentErr, id, message)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
func TestIsUnknown(t *testing.T) {
|
||||
err := zerrors.ThrowUnknown(nil, "id", "msg")
|
||||
ok := zerrors.IsUnknown(err)
|
||||
assert.True(t, ok)
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnknown, zitadelErr.Kind)
|
||||
|
||||
err = errors.New("I am found!")
|
||||
ok = zerrors.IsUnknown(err)
|
||||
assert.False(t, ok)
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, message, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ThrowUnknownf", func(t *testing.T) {
|
||||
format := "formatted %s"
|
||||
arg := "message"
|
||||
expectedMessage := "formatted message"
|
||||
|
||||
err := zerrors.ThrowUnknownf(parentErr, id, format, arg)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
zitadelErr, ok := zerrors.AsZitadelError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, zerrors.KindUnknown, zitadelErr.Kind)
|
||||
|
||||
zitadelError := new(zerrors.ZitadelError)
|
||||
if errors.As(err, &zitadelError) {
|
||||
assert.Equal(t, parentErr, zitadelError.Unwrap())
|
||||
assert.Equal(t, id, zitadelError.ID)
|
||||
assert.Equal(t, expectedMessage, zitadelError.Message)
|
||||
} else {
|
||||
t.Errorf("error is not of type ZitadelError")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IsUnknown", func(t *testing.T) {
|
||||
err := zerrors.ThrowUnknown(parentErr, id, message)
|
||||
isUnknown := zerrors.IsUnknown(err)
|
||||
assert.True(t, isUnknown)
|
||||
})
|
||||
}
|
||||
|
||||
+94
-13
@@ -3,23 +3,93 @@ package zerrors
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
var _ Error = (*ZitadelError)(nil)
|
||||
//go:generate enumer -type=Kind -trimprefix=Kind -json
|
||||
type Kind int
|
||||
|
||||
const (
|
||||
// KindCanceled indicates that the operation was canceled, typically by the
|
||||
// caller.
|
||||
KindCanceled Kind = 1
|
||||
|
||||
// KindUnknown indicates that the operation failed for an unknown reason.
|
||||
KindUnknown Kind = 2
|
||||
|
||||
// KindInvalidArgument indicates that client supplied an invalid argument.
|
||||
KindInvalidArgument Kind = 3
|
||||
|
||||
// KindDeadlineExceeded indicates that deadline expired before the operation
|
||||
// could complete.
|
||||
KindDeadlineExceeded Kind = 4
|
||||
|
||||
// KindNotFound indicates that some requested entity (for example, a file or
|
||||
// directory) was not found.
|
||||
KindNotFound Kind = 5
|
||||
|
||||
// KindAlreadyExists indicates that client attempted to create an entity (for
|
||||
// example, a file or directory) that already exists.
|
||||
KindAlreadyExists Kind = 6
|
||||
|
||||
// KindPermissionDenied indicates that the caller doesn't have permission to
|
||||
// execute the specified operation.
|
||||
KindPermissionDenied Kind = 7
|
||||
|
||||
// KindResourceExhausted indicates that some resource has been exhausted. For
|
||||
// example, a per-user quota may be exhausted or the entire file system may
|
||||
// be full.
|
||||
KindResourceExhausted Kind = 8
|
||||
|
||||
// KindPreconditionFailed indicates that the system is not in a state
|
||||
// required for the operation's execution.
|
||||
KindPreconditionFailed Kind = 9
|
||||
|
||||
// KindAborted indicates that operation was aborted by the system, usually
|
||||
// because of a concurrency issue such as a sequencer check failure or
|
||||
// transaction abort.
|
||||
KindAborted Kind = 10
|
||||
|
||||
// KindOutOfRange indicates that the operation was attempted past the valid
|
||||
// range (for example, seeking past end-of-file).
|
||||
KindOutOfRange Kind = 11
|
||||
|
||||
// KindUnimplemented indicates that the operation isn't implemented,
|
||||
// supported, or enabled in this service.
|
||||
KindUnimplemented Kind = 12
|
||||
|
||||
// KindInternal indicates that some invariants expected by the underlying
|
||||
// system have been broken. This Kind is reserved for serious errors.
|
||||
KindInternal Kind = 13
|
||||
|
||||
// KindUnavailable indicates that the service is currently unavailable. This
|
||||
// is usually temporary, so clients can back off and retry idempotent
|
||||
// operations.
|
||||
KindUnavailable Kind = 14
|
||||
|
||||
// KindDataLoss indicates that the operation has resulted in unrecoverable
|
||||
// data loss or corruption.
|
||||
KindDataLoss Kind = 15
|
||||
|
||||
// KindUnauthenticated indicates that the request does not have valid
|
||||
// authentication credentials for the operation.
|
||||
KindUnauthenticated Kind = 16
|
||||
)
|
||||
|
||||
type ZitadelError struct {
|
||||
Kind Kind
|
||||
Parent error
|
||||
Message string
|
||||
ID string
|
||||
}
|
||||
|
||||
func ThrowError(parent error, id, message string) error {
|
||||
return CreateZitadelError(parent, id, message)
|
||||
return CreateZitadelError(KindUnknown, parent, id, message)
|
||||
}
|
||||
|
||||
func CreateZitadelError(parent error, id, message string) *ZitadelError {
|
||||
func CreateZitadelError(kind Kind, parent error, id, message string) *ZitadelError {
|
||||
return &ZitadelError{
|
||||
Kind: kind,
|
||||
Parent: parent,
|
||||
ID: id,
|
||||
Message: message,
|
||||
@@ -58,6 +128,9 @@ func (err *ZitadelError) Is(target error) bool {
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if t.Kind != err.Kind {
|
||||
return false
|
||||
}
|
||||
if t.ID != "" && t.ID != err.ID {
|
||||
return false
|
||||
}
|
||||
@@ -71,16 +144,24 @@ func (err *ZitadelError) Is(target error) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (err *ZitadelError) As(target interface{}) bool {
|
||||
_, ok := target.(**ZitadelError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
reflect.Indirect(reflect.ValueOf(target)).Set(reflect.ValueOf(err))
|
||||
return true
|
||||
}
|
||||
|
||||
func IsZitadelError(err error) bool {
|
||||
zitadelErr := new(ZitadelError)
|
||||
return errors.As(err, &zitadelErr)
|
||||
}
|
||||
|
||||
func AsZitadelError(err error) (*ZitadelError, bool) {
|
||||
zitadelErr := new(ZitadelError)
|
||||
ok := errors.As(err, &zitadelErr)
|
||||
return zitadelErr, ok
|
||||
}
|
||||
|
||||
var _ slog.LogValuer = (*ZitadelError)(nil)
|
||||
|
||||
func (err *ZitadelError) LogValue() slog.Value {
|
||||
return slog.GroupValue(
|
||||
slog.String("kind", err.Kind.String()),
|
||||
slog.String("message", err.Message),
|
||||
slog.String("id", err.ID),
|
||||
slog.Any("parent", err.Parent),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,26 +19,49 @@ func TestErrorMethod(t *testing.T) {
|
||||
assert.Equal(t, subExptected, err.Error())
|
||||
}
|
||||
|
||||
func TestIsZitadelError(t *testing.T) {
|
||||
func TestZitadelError_Is(t *testing.T) {
|
||||
parent := errors.New("parent error")
|
||||
target := zerrors.CreateZitadelError(zerrors.KindAborted, parent, "id", "message")
|
||||
tests := []struct {
|
||||
name string
|
||||
name string // description of this test case
|
||||
err error
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "zitadel error",
|
||||
err: zerrors.ThrowInvalidArgument(nil, "id", "msg"),
|
||||
want: true,
|
||||
name: "wrong type",
|
||||
err: errors.New("some other error"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "other error",
|
||||
err: errors.New("just a random error"),
|
||||
name: "different kind",
|
||||
err: zerrors.CreateZitadelError(zerrors.KindNotFound, parent, "id", "message"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "different id",
|
||||
err: zerrors.CreateZitadelError(zerrors.KindAborted, parent, "otherID", "message"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "different message",
|
||||
err: zerrors.CreateZitadelError(zerrors.KindAborted, parent, "id", "other message"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "different parent",
|
||||
err: zerrors.CreateZitadelError(zerrors.KindAborted, errors.New("other parent"), "id", "message"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "same error",
|
||||
err: zerrors.CreateZitadelError(zerrors.KindAborted, parent, "id", "message"),
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equalf(t, tt.want, zerrors.IsZitadelError(tt.err), "IsZitadelError(%v)", tt.err)
|
||||
got := errors.Is(tt.err, target)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user