Skip to content

Commit

Permalink
Merge pull request #438 from openinfradev/snr_enhanced
Browse files Browse the repository at this point in the history
feature. personalization systemNotifications
  • Loading branch information
ktkfree authored Apr 26, 2024
2 parents eb973fe + e4b33a8 commit 1d20a35
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 55 deletions.
9 changes: 9 additions & 0 deletions internal/delivery/http/system-notification-rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp
}
dto.OrganizationId = organizationId

if !dto.SystemNotificationCondition.EnablePortal {
ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid EnablePortal"), "SNR_INVALID_ENABLE_PORTAL", ""))
return
}

id, err := h.usecase.Create(r.Context(), dto)
if err != nil {
ErrorJSON(w, r, err)
Expand Down Expand Up @@ -239,6 +244,10 @@ func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.Resp
dto.OrganizationId = organizationId
dto.ID = systemNotificationRuleId

if !dto.SystemNotificationCondition.EnablePortal {
ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid EnablePortal"), "SNR_INVALID_ENABLE_PORTAL", ""))
return
}
err = h.usecase.Update(r.Context(), dto)
if err != nil {
ErrorJSON(w, r, err)
Expand Down
1 change: 1 addition & 0 deletions internal/model/system-notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type SystemNotification struct {
Status domain.SystemNotificationActionStatus `gorm:"index"`
Read bool `gorm:"-:all"`
Readers []User `gorm:"many2many:system_notification_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"`
SystemNotificationRuleId *uuid.UUID
}

type SystemNotificationAction struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/repository/organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (r *OrganizationRepository) Fetch(ctx context.Context, pg *pagination.Pagin
// [TODO] more pretty!
for _, filter := range pg.Filters {
if filter.Relation == "Admin" {
db = db.Joins("left outer join users on users.id::text = organizations.admin_id::text").
db = db.Joins("join users on users.id::text = organizations.admin_id::text").
Where("users.name ilike ?", "%"+filter.Values[0]+"%")
break
}
Expand Down
4 changes: 2 additions & 2 deletions internal/repository/system-notification-rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ func (r *SystemNotificationRuleRepository) FetchWithOrganization(ctx context.Con
// [TODO] more pretty!
for _, filter := range pg.Filters {
if filter.Relation == "TargetUsers" {
db = db.Joins("left outer join system_notification_rule_users on system_notification_rules.id = system_notification_rule_users.system_notification_rule_id").
Joins("left outer join users on system_notification_rule_users.user_id = users.id").
db = db.Joins("join system_notification_rule_users on system_notification_rules.id = system_notification_rule_users.system_notification_rule_id").
Joins("join users on system_notification_rule_users.user_id = users.id").
Where("users.name ilike ?", "%"+filter.Values[0]+"%")
break
}
Expand Down
25 changes: 8 additions & 17 deletions internal/repository/system-notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ func (r *SystemNotificationRepository) FetchSystemNotifications(ctx context.Cont
Preload("Cluster", "status = 2").
Preload("Organization").
Joins("join clusters on clusters.id = system_notifications.cluster_id AND clusters.status = 2").
Joins("left outer join system_notification_rules ON system_notification_rules.id = system_notifications.system_notification_rule_id").
Joins("left outer join system_notification_rule_users ON system_notification_rule_users.system_notification_rule_id = system_notifications.system_notification_rule_id").
Where("system_notification_rule_users.user_id is null OR system_notification_rule_users.user_id = ?", userInfo.GetUserId()).
Where("system_notifications.organization_id = ? AND system_notifications.notification_type = 'SYSTEM_NOTIFICATION'", organizationId)

readFilter := pg.GetFilter("read")
Expand Down Expand Up @@ -140,26 +143,14 @@ func (r *SystemNotificationRepository) FetchPodRestart(ctx context.Context, orga
}

func (r *SystemNotificationRepository) Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) {
systemNotification := model.SystemNotification{
ID: uuid.New(),
OrganizationId: dto.OrganizationId,
Name: dto.Name,
Severity: dto.Severity,
MessageTitle: dto.MessageTitle,
MessageContent: dto.MessageContent,
MessageActionProposal: dto.MessageActionProposal,
ClusterId: dto.ClusterId,
Node: dto.Node,
GrafanaUrl: dto.GrafanaUrl,
Summary: dto.Summary,
RawData: dto.RawData,
Status: domain.SystemNotificationActionStatus_CREATED,
}
res := r.db.WithContext(ctx).Create(&systemNotification)

dto.ID = uuid.New()
dto.Status = domain.SystemNotificationActionStatus_CREATED
res := r.db.WithContext(ctx).Create(&dto)
if res.Error != nil {
return uuid.Nil, res.Error
}
return systemNotification.ID, nil
return dto.ID, nil
}

func (r *SystemNotificationRepository) Update(ctx context.Context, dto model.SystemNotification) (err error) {
Expand Down
4 changes: 3 additions & 1 deletion internal/repository/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination.
// [TODO] more pretty!
for _, filter := range pg.Filters {
if filter.Relation == "Roles" {
db = db.Where("id IN (SELECT user_id FROM user_roles WHERE name IN ?)", filter.Values)
db = db.Joins("join user_roles on user_roles.user_id = users.id").
Joins("join roles on roles.id = user_roles.role_id").
Where("roles.name ilike ?", "%"+filter.Values[0]+"%")
break
}
}
Expand Down
29 changes: 18 additions & 11 deletions internal/usecase/system-notification-rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, systemNotifi
userId := user.GetUserId()
systemNotificationRule.UpdatorId = &userId

if systemNotificationRule.IsSystem {
return out, httpErrors.NewBadRequestError(fmt.Errorf("cannot delete system rules"), "SNR_CANNOT_DELETE_SYSTEM_RULE", "")
}

err = u.repo.Delete(ctx, systemNotificationRule)
if err != nil {
return out, err
Expand All @@ -173,10 +177,13 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
return err
}

organizationAdmin, err := u.userRepo.GetByUuid(ctx, *organization.AdminId)
if err != nil {
return err
}
/*
// 240426 : 기본 알림 설정은 "전체" 를 대상자로 한다.
organizationAdmin, err := u.userRepo.GetByUuid(ctx, *organization.AdminId)
if err != nil {
return err
}
*/

pg := pagination.NewPaginationWithFilter("is_system", "", "$eq", []string{"1"})
templates, err := u.systemNotificationTemplateRepo.Fetch(ctx, pg)
Expand Down Expand Up @@ -204,7 +211,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
EnableEmail: true,
EnablePortal: true,
},
TargetUsers: []model.User{organizationAdmin},
TargetUsers: []model.User{},
MessageTitle: "CPU 사용량이 높습니다",
MessageContent: "스택 (<<STACK>>)의 노드(<<INSTANCE>>)의 idle process의 cpu 점유율이 3분 동안 0% 입니다. (현재 사용률 {{$value}}). 워커 노드 CPU가 과부하 상태입니다. 일시적인 서비스 Traffic 증가, Workload의 SW 오류, Server HW Fan Fail등 다양한 원인으로 인해 발생할 수 있습니다.",
MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행 되는 pod중 CPU 자원을 많이 점유하는 pod의 설정을 점검해 보시길 제안드립니다. 예를 들어 pod spec의 limit 설정으로 과도한 CPU자원 점유을 막을 수 있습니다.",
Expand All @@ -230,7 +237,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
EnableEmail: true,
EnablePortal: true,
},
TargetUsers: []model.User{organizationAdmin},
TargetUsers: []model.User{},
MessageTitle: "메모리 사용량이 높습니다",
MessageContent: "스택 (<<STACK>>)의 노드(<<INSTANCE>>)의 Memory 사용량이 3분동안 80% 를 넘어서고 있습니다. (현재 사용률 {{$value}}). 워커 노드의 Memory 사용량이 80%를 넘었습니다. 일시적인 서비스 증가 및 SW 오류등 다양한 원인으로 발생할 수 있습니다.",
MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행되는 pod중 Memory 사용량이 높은 pod들에 대한 점검을 제안드립니다.",
Expand All @@ -256,7 +263,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
EnableEmail: true,
EnablePortal: true,
},
TargetUsers: []model.User{organizationAdmin},
TargetUsers: []model.User{},
MessageTitle: "노드 디스크 사용량이 높습니다.",
MessageContent: "지난 6시간동안의 추세로 봤을 때, 스택 (<<STACK>>)의 노드(<<INSTANCE>>)의 root 볼륨은 24시간 안에 Disk full이 예상됨. 현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰 것으로 예상됩니다.",
MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.",
Expand All @@ -282,7 +289,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
EnableEmail: true,
EnablePortal: true,
},
TargetUsers: []model.User{organizationAdmin},
TargetUsers: []model.User{},
MessageTitle: "PVC 사용량이 높습니다.",
MessageContent: "지난 6시간동안의 추세로 봤을 때, 스택 (<<INSTANCE>>)의 파드(<<PVC>>)가 24시간 안에 Disk full이 예상됨. 현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰것으로 예상됩니다. (<<STACK>> 스택, <<PVC>> PVC)",
MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.",
Expand All @@ -308,7 +315,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
EnableEmail: true,
EnablePortal: true,
},
TargetUsers: []model.User{organizationAdmin},
TargetUsers: []model.User{},
MessageTitle: "스택의 Pod가 재기동되고 있습니다.",
MessageContent: "스택 (<<STACK>>)의 파드(<<POD>>)가 30분 동안 5회 이상 재기동 ({{$value}} 회). 특정 Pod가 빈번하게 재기동 되고 있습니다. 점검이 필요합니다. (<<STACK>> 스택, <<POD>> 파드)",
MessageActionProposal: "pod spec. 에 대한 점검이 필요합니다. pod의 log 및 status를 확인해 주세요.",
Expand All @@ -334,7 +341,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
EnableEmail: true,
EnablePortal: true,
},
TargetUsers: []model.User{organizationAdmin},
TargetUsers: []model.User{},
MessageTitle: "정책 위반(<<KIND>> / <<NAME>>)",
MessageContent: "스택 (<<STACK>>)의 자원(<<VIOLATING_KIND>> - <<VIOLATING_NAMESPACE>> / <<VIOLATING_NAME>>)에서 정책(<<KIND>> / <<NAME>>)위반이 발생했습니다. 메시지 - <<VIOLATION_MSG>>",
MessageActionProposal: "정책위반이 발생하였습니다.(<<KIND>> / <<NAME>>)",
Expand All @@ -360,7 +367,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c
EnableEmail: true,
EnablePortal: true,
},
TargetUsers: []model.User{organizationAdmin},
TargetUsers: []model.User{},
MessageTitle: "정책 위반(<<KIND>> / <<NAME>>) 시도",
MessageContent: "스택 (<<STACK>>)의 자원(<<VIOLATING_KIND>> - <<VIOLATING_NAMESPACE>> / <<VIOLATING_NAME>>)에서 정책(<<KIND>> / <<NAME>>)위반 시도가 발생했습니다. 메시지 - <<VIOLATION_MSG>>",
MessageActionProposal: "정책위반이 시도가 발생하였습니다.(<<KIND>> / <<NAME>>)",
Expand Down
4 changes: 4 additions & 0 deletions internal/usecase/system-notification-template.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ func (u *SystemNotificationTemplateUsecase) Delete(ctx context.Context, systemNo
userId := user.GetUserId()
systemNotificationTemplate.UpdatorId = &userId

if systemNotificationTemplate.IsSystem {
return httpErrors.NewBadRequestError(fmt.Errorf("cannot delete systemNotificationTemplate"), "SNT_CANNOT_DELETE_SYSTEM_TEMPLATE", "")
}

// check if used
// system_notification_rules
pg := pagination.NewPaginationWithFilter("system_notification_template_id", "", "$eq", []string{systemNotificationTemplateId.String()})
Expand Down
40 changes: 22 additions & 18 deletions internal/usecase/system-notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,27 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre
node = systemNotification.Labels.Instance
}

var systemNotificationRuleId *uuid.UUID
if systemNotification.Annotations.SystemNotificationRuleId != "" {
id, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId)
if err == nil {
systemNotificationRuleId = &id
}
}

dto := model.SystemNotification{
OrganizationId: organizationId,
Name: systemNotification.Labels.AlertName,
Severity: systemNotification.Labels.Severity,
Node: node,
MessageTitle: systemNotification.Annotations.Message,
MessageContent: systemNotification.Annotations.Description,
MessageActionProposal: systemNotification.Annotations.Checkpoint,
Summary: systemNotification.Annotations.Summary,
ClusterId: domain.ClusterId(clusterId),
GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)),
RawData: rawData,
OrganizationId: organizationId,
Name: systemNotification.Labels.AlertName,
Severity: systemNotification.Labels.Severity,
Node: node,
MessageTitle: systemNotification.Annotations.Message,
MessageContent: systemNotification.Annotations.Description,
MessageActionProposal: systemNotification.Annotations.Checkpoint,
Summary: systemNotification.Annotations.Summary,
ClusterId: domain.ClusterId(clusterId),
GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)),
RawData: rawData,
SystemNotificationRuleId: systemNotificationRuleId,
}

_, err = u.repo.Create(ctx, dto)
Expand All @@ -128,13 +137,8 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre
}

// 사용자가 생성한 알림
if systemNotification.Annotations.SystemNotificationRuleId != "" {
systemNotificationRuleId, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId)
if err != nil {
log.Error(ctx, "Failed to parse uuid ", err)
continue
}
rule, err := u.systemNotificationRuleRepo.Get(ctx, systemNotificationRuleId)
if systemNotificationRuleId != nil {
rule, err := u.systemNotificationRuleRepo.Get(ctx, *systemNotificationRuleId)
if err != nil {
log.Error(ctx, "Failed to get systemNotificationRule ", err)
continue
Expand Down
13 changes: 8 additions & 5 deletions pkg/httpErrors/errorCode.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,20 @@ var errorMap = map[ErrorCode]string{
"AL_NOT_FOUND_ALERT": "지정한 앨럿이 존재하지 않습니다.",

// SystemNotificationTemplate
"SNT_CREATE_ALREADY_EXISTED_NAME": "알림템플릿에 이미 존재하는 이름입니다.",
"SNT_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿을 가져오는데 실패했습니다.",
"SNT_FAILED_UPDATE_ORGANIZATION": "알림템플릿에 조직을 설정하는데 실패했습니다.",
"SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.",
"SNT_FAILED_DELETE_EXIST_RULES": "알림템플릿을 사용하고 있는 알림 설정이 있습니다. 알림 설정을 삭제하세요.",
"SNT_CREATE_ALREADY_EXISTED_NAME": "알림템플릿에 이미 존재하는 이름입니다.",
"SNT_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿을 가져오는데 실패했습니다.",
"SNT_FAILED_UPDATE_ORGANIZATION": "알림템플릿에 조직을 설정하는데 실패했습니다.",
"SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.",
"SNT_FAILED_DELETE_EXIST_RULES": "알림템플릿을 사용하고 있는 알림 설정이 있습니다. 알림 설정을 삭제하세요.",
"SNT_CANNOT_DELETE_SYSTEM_TEMPLATE": "시스템 알림템플릿은 삭제 할 수 없습니다.",

// SystemNotificationRule
"SNR_CREATE_ALREADY_EXISTED_NAME": "알림 설정에 이미 존재하는 이름입니다.",
"SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE": "알림 설정을 가져오는데 실패했습니다.",
"SNR_FAILED_UPDATE_ORGANIZATION": "알림 설정에 조직을 설정하는데 실패했습니다.",
"SNR_NOT_EXISTED_SYSTEM_NOTIFICATION_RULE": "업데이트할 알림 설정이 존재하지 않습니다.",
"SNR_INVALID_ENABLE_PORTAL": "알림 방법의 포탈은 설정을 변경할 수 없습니다.",
"SNR_CANNOT_DELETE_SYSTEM_RULE": "시스템 알림 설정은 삭제 할 수 없습니다.",

// AppGroup
"AG_NOT_FOUND_CLUSTER": "지장한 클러스터가 존재하지 않습니다.",
Expand Down
2 changes: 2 additions & 0 deletions scripts/init_postgres.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ALTER DATABASE tks SET timezone = 'Asia/Seoul';

## Roles
insert into roles ( id, name, description, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'tks-admin', 'tks-admin', now(), now() );
insert into roles ( id, name, description, created_at, updated_at ) values ( 'b2b689f0-ceeb-46c2-b280-0bc06896acd1', 'admin', 'admin', now(), now() );
Expand Down

0 comments on commit 1d20a35

Please sign in to comment.