Skip to content

Commit

Permalink
feat: add endpoint to save notification silences
Browse files Browse the repository at this point in the history
  • Loading branch information
adityathebe committed Sep 10, 2024
1 parent 204ae9b commit f48f7f4
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 71 deletions.
11 changes: 0 additions & 11 deletions fixtures/notifications/silence.yaml

This file was deleted.

21 changes: 20 additions & 1 deletion notification/controllers.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package notification

import (
"encoding/json"
"net/http"

"github.com/flanksource/duty/context"
echoSrv "github.com/flanksource/incident-commander/echo"
"github.com/flanksource/incident-commander/rbac"
"github.com/labstack/echo/v4"
Expand All @@ -13,7 +15,24 @@ func init() {
}

func RegisterRoutes(e *echo.Echo) {
e.GET("/notification/events", func(c echo.Context) error {
g := e.Group("/notification")

g.GET("/events", func(c echo.Context) error {
return c.JSON(http.StatusOK, EventRing.Get())
}, rbac.Authorization(rbac.ObjectMonitor, rbac.ActionRead))

g.POST("/silence", func(c echo.Context) error {
ctx := c.Request().Context().(context.Context)

var req SilenceSaveRequest
if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil {
return err
}

if err := SaveNotificationSilence(ctx, req); err != nil {
return err
}

return nil
}, rbac.Authorization(rbac.ObjectNotificationSilence, rbac.ActionCreate))
}
29 changes: 0 additions & 29 deletions notification/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,32 +462,3 @@ func getEnvForEvent(ctx context.Context, event models.Event, properties map[stri

return env, nil
}

func getSilencedResourceFromCelEnv(celEnv map[string]any) models.NotificationSilenceResource {
var silencedResource models.NotificationSilenceResource
if v, ok := celEnv["config"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.ConfigID = lo.ToPtr(vv["id"].(string))
}
}

if v, ok := celEnv["check"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.CheckID = lo.ToPtr(vv["id"].(string))
}
}

if v, ok := celEnv["canary"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.CanaryID = lo.ToPtr(vv["id"].(string))
}
}

if v, ok := celEnv["component"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.ComponentID = lo.ToPtr(vv["id"].(string))
}
}

return silencedResource
}
94 changes: 94 additions & 0 deletions notification/silence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package notification

import (
"errors"
"time"

"github.com/flanksource/commons/duration"
"github.com/flanksource/duty/context"
"github.com/flanksource/duty/models"
"github.com/samber/lo"
)

type SilenceSaveRequest struct {
models.NotificationSilenceResource
From time.Time `json:"from"`
Until time.Time `json:"until"`
Duration string `json:"duration"`
Description string `json:"description"`
}

func (t *SilenceSaveRequest) Validate() error {
if t.From.IsZero() {
return errors.New("`from` time is required")
}

if t.Until.IsZero() {
if t.Duration == "" {
return errors.New("`until` or `duration` is required")
}

if parsed, err := duration.ParseDuration(t.Duration); err != nil {
return err
} else {
t.Until = t.From.Add(time.Duration(parsed))
}
}

if t.From.After(t.Until) {
return errors.New("`from` time must be before `until` time")
}

if t.NotificationSilenceResource.CanaryID == nil && t.NotificationSilenceResource.CheckID == nil && t.NotificationSilenceResource.ConfigID == nil &&
t.NotificationSilenceResource.ComponentID == nil {
return errors.New("at least one of `config_id`, `canary_id`, `check_id` or `component_id` is required")
}

return nil
}

func SaveNotificationSilence(ctx context.Context, req SilenceSaveRequest) error {
if err := req.Validate(); err != nil {
return err
}

silence := models.NotificationSilence{
NotificationSilenceResource: req.NotificationSilenceResource,
From: req.From,
Until: req.Until,
Description: req.Description,
Source: models.SourceUI,
CreatedBy: lo.ToPtr(ctx.User().ID),
}

return ctx.DB().Create(&silence).Error
}

func getSilencedResourceFromCelEnv(celEnv map[string]any) models.NotificationSilenceResource {
var silencedResource models.NotificationSilenceResource
if v, ok := celEnv["config"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.ConfigID = lo.ToPtr(vv["id"].(string))
}
}

if v, ok := celEnv["check"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.CheckID = lo.ToPtr(vv["id"].(string))
}
}

if v, ok := celEnv["canary"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.CanaryID = lo.ToPtr(vv["id"].(string))
}
}

if v, ok := celEnv["component"]; ok {
if vv, ok := v.(map[string]any); ok {
silencedResource.ComponentID = lo.ToPtr(vv["id"].(string))
}
}

return silencedResource
}
1 change: 1 addition & 0 deletions rbac/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ var dbResourceObjMap = map[string]string{
"networks": ObjectAuthConfidential,
"notification_send_history": ObjectMonitor,
"notifications_summary": ObjectMonitor,
"notification_silences": ObjectNotificationSilence,
"notifications": ObjectDatabaseSettings,
"people_roles": ObjectDatabasePublic,
"people": ObjectPeople,
Expand Down
2 changes: 1 addition & 1 deletion rbac/policies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
- viewer
- principal: editor
acl:
- objects: canaries,catalog,topology,playbooks,kubernetes-proxy
- objects: canaries,catalog,topology,playbooks,kubernetes-proxy,notifcation-silence
actions: create,read,update,delete
- objects: playbooks
actions: run
Expand Down
60 changes: 31 additions & 29 deletions rbac/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,36 +147,38 @@ const (
RoleAgent = "agent"

// Actions
ActionRead = "read"
ActionUpdate = "update"
ActionCreate = "create"
ActionDelete = "delete"
ActionRun = "run"
ActionApprove = "approve"
ActionAll = "*"
ActionCRUD = "create,read,update,delete"
ObjectKubernetesProxy = "kubernetes-proxy"
ActionRead = "read"
ActionUpdate = "update"
ActionCreate = "create"
ActionDelete = "delete"
ActionRun = "run"
ActionApprove = "approve"
ActionAll = "*"
ActionCRUD = "create,read,update,delete"

// Objects
ObjectLogs = "logs"
ObjectAgent = "agent"
ObjectAgentPush = "agent-push"
ObjectArtifact = "artifact"
ObjectAuth = "auth"
ObjectCanary = "canaries"
ObjectCatalog = "catalog"
ObjectConnection = "connection"
ObjectDatabase = "database"
ObjectDatabaseIdentity = "database.identities"
ObjectAuthConfidential = "database.kratos"
ObjectDatabasePublic = "database.public"
ObjectDatabaseSettings = "database.config_scrapers"
ObjectDatabaseSystem = "database.system"
ObjectIncident = "incident"
ObjectMonitor = "database.monitor"
ObjectPlaybooks = "playbooks"
ObjectRBAC = "rbac"
ObjectTopology = "topology"
ObjectPeople = "people"
ObjectKubernetesProxy = "kubernetes-proxy"
ObjectLogs = "logs"
ObjectAgent = "agent"
ObjectAgentPush = "agent-push"
ObjectArtifact = "artifact"
ObjectNotificationSilence = "notification-silence"
ObjectAuth = "auth"
ObjectCanary = "canaries"
ObjectCatalog = "catalog"
ObjectConnection = "connection"
ObjectDatabase = "database"
ObjectDatabaseIdentity = "database.identities"
ObjectAuthConfidential = "database.kratos"
ObjectDatabasePublic = "database.public"
ObjectDatabaseSettings = "database.config_scrapers"
ObjectDatabaseSystem = "database.system"
ObjectIncident = "incident"
ObjectMonitor = "database.monitor"
ObjectPlaybooks = "playbooks"
ObjectRBAC = "rbac"
ObjectTopology = "topology"
ObjectPeople = "people"
)

var (
Expand Down

0 comments on commit f48f7f4

Please sign in to comment.