Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions pkg/api/api/grpc_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ func TestNewGRPCStatus(t *testing.T) {
"messagekey": "InternalServerError",
},
},
{
name: "FailedPrecondition with messageKey override",
err: pkgErr.NewErrorFailedPrecondition("test", "comment required").
WithMessageKey("CommentRequiredForUpdating"),
expectedCode: codes.FailedPrecondition,
expectedMessage: "test:comment required",
expectedReason: "FAILED_PRECONDITION",
expectedMetadata: map[string]string{
"messagekey": "CommentRequiredForUpdating",
},
},
{
name: "Non-BucketeerError",
err: errors.New("standard error"),
Expand Down
16 changes: 8 additions & 8 deletions pkg/autoops/api/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,13 @@ var (
statusProgressiveRolloutWaitingOrRunningExperimentExists = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(
pkgErr.AutoopsPackageName,
"cannot create a progressive rollout when there is a scheduled or running experiment",
))
"cannot create a progressive rollout when there is a scheduled or running experiment").
WithMessageKey("AutoOpsWaitingOrRunningExperimentExists"))
statusProgressiveRolloutInsufficientVariations = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(
pkgErr.AutoopsPackageName,
"the feature must have at least 2 variations when creating a progressive rollout",
))
"the feature must have at least 2 variations when creating a progressive rollout").
WithMessageKey("AutoOpsInvalidVariationSize"))
statusProgressiveRolloutControlVariationRequired = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(
pkgErr.AutoopsPackageName,
Expand All @@ -241,8 +241,8 @@ var (
statusProgressiveRolloutVariationsMustBeDifferent = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(
pkgErr.AutoopsPackageName,
"control and target variations must be different for a progressive rollout",
))
"control and target variations must be different for a progressive rollout").
WithMessageKey("ProgressiveRolloutVariationsMustBeDifferent"))
statusProgressiveRolloutControlVariationNotFound = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(
pkgErr.AutoopsPackageName,
Expand All @@ -258,8 +258,8 @@ var (
statusProgressiveRolloutInvalidScheduleSpans = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(
pkgErr.AutoopsPackageName,
"the span of time for each scheduled time must be at least 5 minutes for a progressive rollout",
))
"the span of time for each scheduled time must be at least 5 minutes for a progressive rollout").
WithMessageKey("AutoOpsInvalidScheduleSpans"))
statusProgressiveRolloutScheduleExecutedAtRequired = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(
pkgErr.AutoopsPackageName,
Expand Down
13 changes: 8 additions & 5 deletions pkg/environment/api/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ var (
statusCannotUpdateSystemAdmin = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(
pkgErr.EnvironmentPackageName,
"cannot update system admin organization",
))
"cannot update system admin organization").
WithMessageKey("CannotUpdateSystemAdminOrganizationError"))
statusEnvironmentNotFound = api.NewGRPCStatus(
pkgErr.NewErrorNotFound(pkgErr.EnvironmentPackageName, "environment not found", "Environment"))
statusProjectNotFound = api.NewGRPCStatus(
Expand All @@ -104,17 +104,20 @@ var (
statusOrganizationAlreadyExists = api.NewGRPCStatus(
pkgErr.NewErrorAlreadyExists(pkgErr.EnvironmentPackageName, "organization already exists"))
statusProjectDisabled = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.EnvironmentPackageName, "project disabled"))
pkgErr.NewErrorFailedPrecondition(pkgErr.EnvironmentPackageName, "project disabled").
WithMessageKey("ProjectDisabled"))
statusUnauthenticated = api.NewGRPCStatus(
pkgErr.NewErrorUnauthenticated(pkgErr.EnvironmentPackageName, "unauthenticated"))
statusPermissionDenied = api.NewGRPCStatus(
pkgErr.NewErrorPermissionDenied(pkgErr.EnvironmentPackageName, "permission denied"))
statusAccountNotFound = api.NewGRPCStatus(
pkgErr.NewErrorNotFound(pkgErr.EnvironmentPackageName, "account not found", "Account"))
statusDemoSiteDisabled = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.EnvironmentPackageName, "demo site is not enabled"))
pkgErr.NewErrorFailedPrecondition(pkgErr.EnvironmentPackageName, "demo site is not enabled").
WithMessageKey("DemoSiteNotEnabled"))
statusUserAlreadyInOrganization = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.EnvironmentPackageName, "user already in organization"))
pkgErr.NewErrorFailedPrecondition(pkgErr.EnvironmentPackageName, "user already in organization").
WithMessageKey("UserAlreadyInOrganization"))
statusInvalidAutoArchiveUnusedDays = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgNotMatchFormat(
pkgErr.EnvironmentPackageName,
Expand Down
15 changes: 13 additions & 2 deletions pkg/error/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,24 @@ type BktError struct {
wrappedError error
field string // optional

embeddedKeyValues map[string]string
embeddedKeyValues map[string]string
messageKeyOverride string
}

func (e *BktError) PackageName() string { return e.packageName }
func (e *BktError) ErrorType() ErrorType { return e.errorType }

func (e *BktError) MessageKey() string { return string(e.errorType) }
func (e *BktError) MessageKey() string {
if e.messageKeyOverride != "" {
return e.messageKeyOverride
}
return string(e.errorType)
}

func (e *BktError) WithMessageKey(key string) *BktError {
e.messageKeyOverride = key
return e
}
func (e *BktError) EmbeddedKeyValues() map[string]string { return e.embeddedKeyValues }

func (e *BktError) Error() string {
Expand Down
25 changes: 25 additions & 0 deletions pkg/error/error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,31 @@ func TestErrorType_String(t *testing.T) {
}
}

func TestMessageKey(t *testing.T) {
t.Parallel()

t.Run("default returns error type", func(t *testing.T) {
t.Parallel()
err := NewErrorFailedPrecondition("test", "precondition failed")
assert.Equal(t, "FailedPreconditionError", err.MessageKey())
})

t.Run("override replaces default", func(t *testing.T) {
t.Parallel()
err := NewErrorFailedPrecondition("test", "comment required").
WithMessageKey("CommentRequiredForUpdating")
assert.Equal(t, "CommentRequiredForUpdating", err.MessageKey())
assert.Equal(t, ErrorTypeFailedPrecondition, err.ErrorType())
})

t.Run("empty override falls back to default", func(t *testing.T) {
t.Parallel()
err := NewErrorFailedPrecondition("test", "generic").
WithMessageKey("")
assert.Equal(t, "FailedPreconditionError", err.MessageKey())
})
}

func TestErrorWrapComplex(t *testing.T) {
t.Parallel()

Expand Down
28 changes: 18 additions & 10 deletions pkg/feature/api/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ var (
statusMissingFeatureTags = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(pkgErr.FeaturePackageName, "feature must contain one or more tags", "Tag"))
statusCommentRequiredForUpdating = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "a comment is required for updating"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "a comment is required for updating").
WithMessageKey("CommentRequiredForUpdating"))
statusMissingSegmentID = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(pkgErr.FeaturePackageName, "missing segment id", "Segment"))
statusMissingSegmentUsersData = api.NewGRPCStatus(
Expand Down Expand Up @@ -121,11 +122,14 @@ var (
statusAlreadyExists = api.NewGRPCStatus(
pkgErr.NewErrorAlreadyExists(pkgErr.FeaturePackageName, "already exists"))
statusSegmentUsersAlreadyUploading = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment users already uploading"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment users already uploading").
WithMessageKey("SegmentUsersAlreadyUploading"))
statusSegmentStatusNotSuceeded = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment status is not suceeded"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment status is not suceeded").
Comment thread
t-kikuc marked this conversation as resolved.
Outdated
WithMessageKey("SegmentStatusNotSucceeded"))
statusSegmentInUse = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment is in use"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment is in use").
WithMessageKey("SegmentInUse"))
// segment rules
statusExceededMaxSegmentRules = api.NewGRPCStatus(
pkgErr.NewErrorExceededMax(
Expand Down Expand Up @@ -202,16 +206,18 @@ var (
statusPermissionDenied = api.NewGRPCStatus(
pkgErr.NewErrorPermissionDenied(pkgErr.FeaturePackageName, "permission denied"))
statusWaitingOrRunningExperimentExists = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "experiment in waiting or running status exists"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "experiment in waiting or running status exists").
WithMessageKey("HasWaitingOrRunningExperiment"))
statusInvalidArchive = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(
pkgErr.FeaturePackageName,
"can't archive because this feature is used as a prerequsite"))
"can't archive because this feature is used as a prerequsite").
Comment thread
t-kikuc marked this conversation as resolved.
Outdated
WithMessageKey("InvalidArchive"))
statusVariationInUseByOtherFeatures = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(
pkgErr.FeaturePackageName,
"can't remove this variation because it is used as a prerequisite or rule in other features",
))
"can't remove this variation because it is used as a prerequisite or rule in other features").
WithMessageKey("InvalidChangingVariation"))
// flag trigger
statusMissingTriggerFeatureID = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(pkgErr.FeaturePackageName, "missing trigger feature id", "FeatureFlagID"))
Expand All @@ -224,7 +230,8 @@ var (
statusSecretRequired = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(pkgErr.FeaturePackageName, "trigger secret is required", "TriggerSecret"))
statusTriggerAlreadyDisabled = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "trigger already disabled"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "trigger already disabled").
WithMessageKey("TriggerAlreadyDisabled"))
statusTriggerNotFound = api.NewGRPCStatus(
pkgErr.NewErrorNotFound(pkgErr.FeaturePackageName, "trigger not found", "FlagTrigger"))
statusTriggerDisableFailed = api.NewGRPCStatus(
Expand Down Expand Up @@ -283,7 +290,8 @@ var (
statusScheduledFlagChangeNotFound = api.NewGRPCStatus(
pkgErr.NewErrorNotFound(pkgErr.FeaturePackageName, "scheduled flag change not found", "ScheduledFlagChange"))
statusScheduledFlagChangeNotPending = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "scheduled flag change is not pending"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "scheduled flag change is not pending").
WithMessageKey("ScheduledFlagChangeNotPending"))
statusEmptyPayload = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(pkgErr.FeaturePackageName, "payload must contain at least one change", "Payload"))
statusInvalidVariationReference = api.NewGRPCStatus(
Expand Down
3 changes: 2 additions & 1 deletion pkg/notification/api/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ var (
statusNotificationAlreadyPublished = api.NewGRPCStatus(
bkterr.NewErrorFailedPrecondition(
bkterr.NotificationPackageName,
"notification is already published"))
"notification is already published").
WithMessageKey("NotificationAlreadyPublished"))
statusInvalidCursor = api.NewGRPCStatus(
bkterr.NewErrorInvalidArgNotMatchFormat(
bkterr.NotificationPackageName,
Expand Down
3 changes: 2 additions & 1 deletion pkg/tag/api/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ var (
err.NewErrorInvalidArgEmpty(err.TagPackageName, "entity_type must be specified", "EntityType"),
)
statusTagInUsed = api.NewGRPCStatus(
err.NewErrorFailedPrecondition(err.TagPackageName, "tag is in use"))
err.NewErrorFailedPrecondition(err.TagPackageName, "tag is in use").
WithMessageKey("TagInUse"))
statusInvalidCursor = api.NewGRPCStatus(
err.NewErrorInvalidArgNotMatchFormat(err.TagPackageName, "cursor is invalid", "Cursor"),
)
Expand Down
10 changes: 9 additions & 1 deletion ui/dashboard/src/@locales/en/backend.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,15 @@
"AutoOpsProgressiveRolloutInProgress": "There is a Proressive Rollout in progress. Please stop or delete it before making changes",
"StartAtIsAfterEndAt": "Start at must be before end at",
"PeriodOutOfRange": "The period must be within the last 30 days",
"ProjectDisabled": "Project is disabled"
"ProjectDisabled": "Project is disabled",
"CannotUpdateSystemAdminOrganizationError": "System admin organization cannot be disabled or archived",
"DemoSiteNotEnabled": "Demo site is not enabled",
"UserAlreadyInOrganization": "User is already a member of this organization",
"TriggerAlreadyDisabled": "Trigger is already disabled",
"ScheduledFlagChangeNotPending": "Scheduled flag change is not in pending status",
"NotificationAlreadyPublished": "Notification has already been published",
"TagInUse": "Tag cannot be deleted because it is in use",
"ProgressiveRolloutVariationsMustBeDifferent": "Control and target variations must be different for a progressive rollout"
},
"domainEvents": {
"UnknownOperation": "An unknown operation occurred",
Expand Down
9 changes: 8 additions & 1 deletion ui/dashboard/src/@locales/ja/backend.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,14 @@
"AutoOpsProgressiveRolloutInProgress": "実行中のプログレッシブロールアウトがあります。更新する場合はプログレッシブロールアウトを停止もしくは、削除してください",
"StartAtIsAfterEndAt": "開始時間は終了時間以前を指定してください",
"PeriodOutOfRange": "期間は過去30日以内を選択してください",
"ProjectDisabled": "プロジェクトが無効化されています"
"ProjectDisabled": "プロジェクトが無効化されています",
"DemoSiteNotEnabled": "デモサイトが有効化されていません",
"UserAlreadyInOrganization": "ユーザーは既にこのオーガニゼーションのメンバーです",
"TriggerAlreadyDisabled": "トリガーは既に無効化されています",
"ScheduledFlagChangeNotPending": "スケジュールされたフラグ変更は保留中ではありません",
"NotificationAlreadyPublished": "通知は既に公開されています",
"TagInUse": "タグが使用されているため削除できません",
"ProgressiveRolloutVariationsMustBeDifferent": "プログレッシブロールアウトのコントロールバリエーションとターゲットバリエーションは異なる必要があります"
},
"domainEvents": {
"UnknownOperation": "不明な操作が実行されました",
Expand Down
Loading