Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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 @@ -142,6 +142,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 @@ -80,13 +80,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
26 changes: 17 additions & 9 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"))
statusSegmentStatusNotSuceeded = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment status is not suceeded"))
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment users already uploading").
WithMessageKey("SegmentUsersAlreadyUploading"))
statusSegmentStatusNotSucceeded = api.NewGRPCStatus(
pkgErr.NewErrorFailedPrecondition(pkgErr.FeaturePackageName, "segment status is not succeeded").
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,11 +206,13 @@ 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 prerequisite").
WithMessageKey("InvalidArchive"))
// flag trigger
statusMissingTriggerFeatureID = api.NewGRPCStatus(
pkgErr.NewErrorInvalidArgEmpty(pkgErr.FeaturePackageName, "missing trigger feature id", "FeatureFlagID"))
Expand All @@ -219,7 +225,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 @@ -278,7 +285,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
2 changes: 1 addition & 1 deletion pkg/feature/api/segment_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ func (s *FeatureService) BulkDownloadSegmentUsers(
return nil, api.NewGRPCStatus(err).Err()
}
if segment.Status != featureproto.Segment_SUCEEDED {
return nil, statusSegmentStatusNotSuceeded.Err()
return nil, statusSegmentStatusNotSucceeded.Err()
}
stateVal := int32(req.State)
users, _, err := s.segmentUserStorage.ListSegmentUsers(
Expand Down
4 changes: 2 additions & 2 deletions pkg/feature/api/segment_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ func TestBulkDownloadSegmentUsersMySQL(t *testing.T) {
expectedErr: statusSegmentNotFound.Err(),
},
{
desc: "ErrSegmentStatusNotSuceeded",
desc: "ErrSegmentStatusNotSucceeded",
setup: func(s *FeatureService) {
s.segmentStorage.(*storagemock.MockSegmentStorage).EXPECT().GetSegment(
gomock.Any(), gomock.Any(), gomock.Any(),
Expand All @@ -286,7 +286,7 @@ func TestBulkDownloadSegmentUsersMySQL(t *testing.T) {
environmentId: "ns0",
segmentID: "id",
state: featureproto.SegmentUser_INCLUDED,
expectedErr: statusSegmentStatusNotSuceeded.Err(),
expectedErr: statusSegmentStatusNotSucceeded.Err(),
},
}
for _, tc := range testcases {
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
2 changes: 1 addition & 1 deletion pkg/subscriber/processor/segment_user_persister.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ func (p *segmentUserPersister) handleChunk(ctx context.Context, chunk map[string
}
msg.Ack()
p.logger.Debug(
"suceeded to persist segment users",
"succeeded to persist segment users",
zap.String("msgID", msg.ID),
zap.String("environmentId", event.EnvironmentId),
zap.String("segmentId", event.SegmentId),
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
2 changes: 1 addition & 1 deletion test/e2e/feature/feature_auto_archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ func executeBatchJob(t *testing.T, client btclient.Client, job btproto.BatchJob)
// FailedPrecondition errors are expected when the environment contains
// features with prerequisites that can't be archived. This is not a test failure.
if strings.Contains(err.Error(), "FailedPrecondition") ||
strings.Contains(err.Error(), "used as a prerequsite") {
strings.Contains(err.Error(), "used as a prerequisite") {
t.Logf("Batch job completed with expected prerequisite warning: %v", err)
return
}
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 @@ -162,7 +162,15 @@
"VariationInUseByFeatureFlagRuleError": "This variation cannot be deleted because the flag \"{{featureName}}\" uses it in a targeting rule. Remove the rule from that flag first.",
"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 @@ -188,7 +188,14 @@
"VariationInUseByFeatureFlagRuleError": "このバリエーションはフラグ「{{featureName}}」のターゲティングルールで使用されているため削除できません。先に該当フラグのルールを削除してください。",
"StartAtIsAfterEndAt": "開始時間は終了時間以前を指定してください",
"PeriodOutOfRange": "期間は過去30日以内を選択してください",
"ProjectDisabled": "プロジェクトが無効化されています"
"ProjectDisabled": "プロジェクトが無効化されています",
"DemoSiteNotEnabled": "デモサイトが有効化されていません",
"UserAlreadyInOrganization": "ユーザーは既にこのオーガニゼーションのメンバーです",
"TriggerAlreadyDisabled": "トリガーは既に無効化されています",
"ScheduledFlagChangeNotPending": "スケジュールされたフラグ変更は保留中ではありません",
"NotificationAlreadyPublished": "通知は既に公開されています",
"TagInUse": "タグが使用されているため削除できません",
"ProgressiveRolloutVariationsMustBeDifferent": "プログレッシブロールアウトのコントロールバリエーションとターゲットバリエーションは異なる必要があります"
},
"domainEvents": {
"UnknownOperation": "不明な操作が実行されました",
Expand Down
Loading